]> git.vomp.tv Git - makedevenv.git/commitdiff
Initial import
authorChris Tallon <chris@vomp.tv>
Sat, 23 Jun 2012 15:04:02 +0000 (16:04 +0100)
committerChris Tallon <chris@vomp.tv>
Sat, 23 Jun 2012 15:04:02 +0000 (16:04 +0100)
78 files changed:
.gitignore [new file with mode: 0644]
busybox/README [new file with mode: 0644]
busybox/autobuild [new file with mode: 0755]
busybox/build [new file with mode: 0755]
busybox/clean [new file with mode: 0644]
busybox/config-dev-3 [new file with mode: 0644]
busybox/config-dongle-2 [new file with mode: 0644]
busybox/fullclean [new file with mode: 0755]
busybox/prepare [new file with mode: 0755]
crosstool/README [new file with mode: 0644]
crosstool/autobuild [new file with mode: 0755]
crosstool/build [new file with mode: 0755]
crosstool/clean [new file with mode: 0755]
crosstool/fullclean [new file with mode: 0755]
crosstool/glibc-2.2.5-allow-gcc-4.0-configure.patch [new file with mode: 0644]
crosstool/prepare [new file with mode: 0755]
dongle/README [new file with mode: 0644]
dongle/autobuild [new file with mode: 0755]
dongle/build [new file with mode: 0755]
dongle/devtable [new file with mode: 0644]
dongle/fullclean [new file with mode: 0755]
dongle/prepare [new file with mode: 0755]
dongle/tofs/dev/fb [new symlink]
dongle/tofs/dev/kcore [new symlink]
dongle/tofs/dev/mouse [new symlink]
dongle/tofs/dev/ram [new symlink]
dongle/tofs/dev/ramdisk [new symlink]
dongle/tofs/dev/stderr [new symlink]
dongle/tofs/dev/stdin [new symlink]
dongle/tofs/dev/stdout [new symlink]
dongle/tofs/etc/fstab [new file with mode: 0644]
dongle/tofs/etc/group [new file with mode: 0644]
dongle/tofs/etc/hosts [new file with mode: 0644]
dongle/tofs/etc/inittab [new file with mode: 0644]
dongle/tofs/etc/issue.net [new file with mode: 0644]
dongle/tofs/etc/passwd [new file with mode: 0644]
dongle/tofs/etc/profile [new file with mode: 0644]
dongle/tofs/etc/rcS [new file with mode: 0755]
dongle/tofs/lib/modules/2.4.31/av_core.o [new file with mode: 0644]
dongle/tofs/lib/modules/2.4.31/gfx.o [new file with mode: 0644]
dongle/tofs/lib/modules/2.4.31/ircombo.o [new file with mode: 0644]
dongle/tofs/lib/modules/2.4.31/os_core.o [new file with mode: 0644]
dongle/tofs/lib/modules/2.4.31/osdfb.o [new file with mode: 0644]
jpeg/README [new file with mode: 0644]
jpeg/autobuild [new file with mode: 0755]
jpeg/build [new file with mode: 0755]
jpeg/clean [new file with mode: 0755]
jpeg/fullclean [new file with mode: 0755]
jpeg/prepare [new file with mode: 0755]
kernel/README [new file with mode: 0644]
kernel/autobuild [new file with mode: 0755]
kernel/build [new file with mode: 0755]
kernel/clean [new file with mode: 0755]
kernel/config-dev-5 [new file with mode: 0644]
kernel/config-dongle-2 [new file with mode: 0644]
kernel/fullclean [new file with mode: 0755]
kernel/otherpatches/Makefile.patch [new file with mode: 0644]
kernel/otherpatches/bash4_correction.patch [new file with mode: 0644]
kernel/otherpatches/dongle_version.h [new file with mode: 0644]
kernel/otherpatches/fullduplex.patch [new file with mode: 0644]
kernel/otherpatches/ppcfix.patch [new file with mode: 0644]
kernel/patch [new file with mode: 0755]
kernel/patches-2.4.31/architecture.patch [new file with mode: 0644]
kernel/patches-2.4.31/clockfix.patch [new file with mode: 0644]
kernel/patches-2.4.31/kexec-ppc-2.4.patch [new file with mode: 0644]
kernel/patches-2.4.31/memsize.patch [new file with mode: 0644]
kernel/patches-2.4.31/mvp-version.patch [new file with mode: 0644]
kernel/patches-2.4.31/ppc405-wdt.patch [new file with mode: 0644]
kernel/patches-2.4.31/redwood.c [new file with mode: 0644]
kernel/patches-2.4.31/sdram-bank1.patch [new file with mode: 0644]
kernel/patches-2.4.31/smc91111.patch [new file with mode: 0644]
kernel/prepare [new file with mode: 0755]
lbox_border/README [new file with mode: 0644]
lbox_border/autobuild [new file with mode: 0755]
lbox_border/build [new file with mode: 0755]
lbox_border/clean [new file with mode: 0755]
lbox_border/lbox_border.c [new file with mode: 0644]
makedevenv [new file with mode: 0755]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..a868cc5
--- /dev/null
@@ -0,0 +1,2 @@
+client
+packages
diff --git a/busybox/README b/busybox/README
new file mode 100644 (file)
index 0000000..923dd42
--- /dev/null
@@ -0,0 +1,14 @@
+$1 argument to scripts that have it should be dev or dongle, see autobuild
+for examples.
+
+autobuild   - does full clean then full build
+prepare $1  - unpacks busybox tree into $1 dir
+              only to be used after fullclean (or just un-tarred package)
+build $1 $2 - work with busybox under $1 dir. copy config file $2 to busybox
+              and compile it
+              only to be used on a cleaned busybox tree
+clean $1    - runs make distclean on busybox tree in dir $1
+              makes it ready for build
+fullclean   - removes busybox trees in order to start from scratch
+
+
diff --git a/busybox/autobuild b/busybox/autobuild
new file mode 100755 (executable)
index 0000000..7b708f2
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+./fullclean
+
+./prepare dev
+./prepare dongle
+
+./build dev config-dev-3
+./build dongle config-dongle-2
+
diff --git a/busybox/build b/busybox/build
new file mode 100755 (executable)
index 0000000..4f81d59
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+. ../crosstool/cross-var
+
+cd $1/busybox-1.00
+
+cp ../../$2 .config
+make CROSS=${CROSS}
+make CROSS=${CROSS} install
+
diff --git a/busybox/clean b/busybox/clean
new file mode 100644 (file)
index 0000000..4c42a1c
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+cd $1/busybox-1.00
+make distclean
diff --git a/busybox/config-dev-3 b/busybox/config-dev-3
new file mode 100644 (file)
index 0000000..9badda3
--- /dev/null
@@ -0,0 +1,438 @@
+#
+# Automatically generated make config: don't edit
+#
+HAVE_DOT_CONFIG=y
+
+#
+# General Configuration
+#
+# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set
+CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+# CONFIG_FEATURE_VERBOSE_USAGE is not set
+# CONFIG_FEATURE_INSTALLER is not set
+# CONFIG_LOCALE_SUPPORT is not set
+# CONFIG_FEATURE_DEVFS is not set
+# CONFIG_FEATURE_DEVPTS is not set
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_SUID=y
+CONFIG_FEATURE_SUID_CONFIG=y
+# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set
+# CONFIG_SELINUX is not set
+
+#
+# Build Options
+#
+CONFIG_STATIC=y
+# CONFIG_LFS is not set
+USING_CROSS_COMPILER=y
+CROSS_COMPILER_PREFIX="/opt/crosstool/powerpc-405-linux-gnu/gcc-2.95.3-glibc-2.2.5/bin/powerpc-405-linux-gnu-"
+EXTRA_CFLAGS_OPTIONS=""
+
+#
+# Installation Options
+#
+# CONFIG_INSTALL_NO_USR is not set
+PREFIX="../install"
+
+#
+# Archival Utilities
+#
+# CONFIG_AR is not set
+# CONFIG_BUNZIP2 is not set
+# CONFIG_CPIO is not set
+# CONFIG_DPKG is not set
+# CONFIG_DPKG_DEB is not set
+CONFIG_GUNZIP=y
+# CONFIG_FEATURE_GUNZIP_UNCOMPRESS is not set
+CONFIG_GZIP=y
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+CONFIG_TAR=y
+CONFIG_FEATURE_TAR_CREATE=y
+# CONFIG_FEATURE_TAR_BZIP2 is not set
+# CONFIG_FEATURE_TAR_FROM is not set
+CONFIG_FEATURE_TAR_GZIP=y
+# CONFIG_FEATURE_TAR_COMPRESS is not set
+# CONFIG_FEATURE_TAR_OLDGNU_COMPATABILITY is not set
+CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y
+# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set
+# CONFIG_UNCOMPRESS is not set
+# CONFIG_UNZIP is not set
+
+#
+# Common options for cpio and tar
+#
+# CONFIG_FEATURE_UNARCHIVE_TAPE is not set
+
+#
+# Coreutils
+#
+CONFIG_BASENAME=y
+# CONFIG_CAL is not set
+CONFIG_CAT=y
+CONFIG_CHGRP=y
+CONFIG_CHMOD=y
+CONFIG_CHOWN=y
+CONFIG_CHROOT=y
+# CONFIG_CMP is not set
+CONFIG_CP=y
+CONFIG_CUT=y
+CONFIG_DATE=y
+
+#
+# date (forced enabled for use with watch)
+#
+CONFIG_FEATURE_DATE_ISOFMT=y
+CONFIG_DD=y
+CONFIG_DF=y
+CONFIG_DIRNAME=y
+# CONFIG_DOS2UNIX is not set
+CONFIG_DU=y
+CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K=y
+CONFIG_ECHO=y
+CONFIG_FEATURE_FANCY_ECHO=y
+CONFIG_ENV=y
+# CONFIG_EXPR is not set
+CONFIG_FALSE=y
+# CONFIG_FOLD is not set
+CONFIG_HEAD=y
+# CONFIG_FEATURE_FANCY_HEAD is not set
+# CONFIG_HOSTID is not set
+CONFIG_ID=y
+# CONFIG_INSTALL is not set
+# CONFIG_LENGTH is not set
+CONFIG_LN=y
+# CONFIG_LOGNAME is not set
+CONFIG_LS=y
+CONFIG_FEATURE_LS_FILETYPES=y
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+# CONFIG_FEATURE_LS_RECURSIVE is not set
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+CONFIG_FEATURE_LS_USERNAME=y
+CONFIG_FEATURE_LS_COLOR=y
+# CONFIG_MD5SUM is not set
+CONFIG_MKDIR=y
+# CONFIG_MKFIFO is not set
+CONFIG_MKNOD=y
+CONFIG_MV=y
+# CONFIG_OD is not set
+# CONFIG_PRINTF is not set
+CONFIG_PWD=y
+# CONFIG_REALPATH is not set
+CONFIG_RM=y
+CONFIG_RMDIR=y
+# CONFIG_SEQ is not set
+# CONFIG_SHA1SUM is not set
+CONFIG_SLEEP=y
+# CONFIG_FEATURE_FANCY_SLEEP is not set
+CONFIG_SORT=y
+# CONFIG_STTY is not set
+CONFIG_SYNC=y
+CONFIG_TAIL=y
+# CONFIG_FEATURE_FANCY_TAIL is not set
+# CONFIG_TEE is not set
+CONFIG_TEST=y
+
+#
+# test (forced enabled for use with shell)
+#
+# CONFIG_FEATURE_TEST_64 is not set
+CONFIG_TOUCH=y
+# CONFIG_TR is not set
+CONFIG_TRUE=y
+CONFIG_TTY=y
+CONFIG_UNAME=y
+CONFIG_UNIQ=y
+# CONFIG_USLEEP is not set
+# CONFIG_UUDECODE is not set
+# CONFIG_UUENCODE is not set
+CONFIG_WATCH=y
+# CONFIG_WC is not set
+# CONFIG_WHO is not set
+CONFIG_WHOAMI=y
+CONFIG_YES=y
+
+#
+# Common options for cp and mv
+#
+# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set
+
+#
+# Common options for ls and more
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+CONFIG_FEATURE_HUMAN_READABLE=y
+
+#
+# Console Utilities
+#
+# CONFIG_CHVT is not set
+CONFIG_CLEAR=y
+# CONFIG_DEALLOCVT is not set
+# CONFIG_DUMPKMAP is not set
+# CONFIG_LOADFONT is not set
+# CONFIG_LOADKMAP is not set
+# CONFIG_OPENVT is not set
+CONFIG_RESET=y
+# CONFIG_SETKEYCODES is not set
+
+#
+# Debian Utilities
+#
+# CONFIG_MKTEMP is not set
+# CONFIG_PIPE_PROGRESS is not set
+# CONFIG_READLINK is not set
+# CONFIG_RUN_PARTS is not set
+# CONFIG_START_STOP_DAEMON is not set
+CONFIG_WHICH=y
+
+#
+# Editors
+#
+# CONFIG_AWK is not set
+# CONFIG_PATCH is not set
+CONFIG_SED=y
+CONFIG_VI=y
+CONFIG_FEATURE_VI_COLON=y
+CONFIG_FEATURE_VI_YANKMARK=y
+CONFIG_FEATURE_VI_SEARCH=y
+CONFIG_FEATURE_VI_USE_SIGNALS=y
+CONFIG_FEATURE_VI_DOT_CMD=y
+CONFIG_FEATURE_VI_READONLY=y
+CONFIG_FEATURE_VI_SETOPTS=y
+CONFIG_FEATURE_VI_SET=y
+CONFIG_FEATURE_VI_WIN_RESIZE=y
+CONFIG_FEATURE_VI_OPTIMIZE_CURSOR=y
+
+#
+# Finding Utilities
+#
+CONFIG_FIND=y
+# CONFIG_FEATURE_FIND_MTIME is not set
+# CONFIG_FEATURE_FIND_PERM is not set
+CONFIG_FEATURE_FIND_TYPE=y
+CONFIG_FEATURE_FIND_XDEV=y
+CONFIG_FEATURE_FIND_NEWER=y
+CONFIG_FEATURE_FIND_INUM=y
+CONFIG_GREP=y
+# CONFIG_FEATURE_GREP_EGREP_ALIAS is not set
+CONFIG_FEATURE_GREP_FGREP_ALIAS=y
+# CONFIG_FEATURE_GREP_CONTEXT is not set
+# CONFIG_XARGS is not set
+
+#
+# Init Utilities
+#
+CONFIG_INIT=y
+CONFIG_FEATURE_USE_INITTAB=y
+# CONFIG_FEATURE_INITRD is not set
+# CONFIG_FEATURE_INIT_COREDUMPS is not set
+# CONFIG_FEATURE_EXTRA_QUIET is not set
+# CONFIG_HALT is not set
+# CONFIG_POWEROFF is not set
+CONFIG_REBOOT=y
+# CONFIG_MESG is not set
+
+#
+# Login/Password Management Utilities
+#
+# CONFIG_USE_BB_PWD_GRP is not set
+# CONFIG_ADDGROUP is not set
+# CONFIG_DELGROUP is not set
+# CONFIG_ADDUSER is not set
+# CONFIG_DELUSER is not set
+# CONFIG_GETTY is not set
+# CONFIG_FEATURE_U_W_TMP is not set
+CONFIG_LOGIN=y
+CONFIG_FEATURE_SECURETTY=y
+# CONFIG_PASSWD is not set
+# CONFIG_SU is not set
+# CONFIG_SULOGIN is not set
+# CONFIG_VLOCK is not set
+
+#
+# Common options for adduser, deluser, login, su
+#
+# CONFIG_FEATURE_SHADOWPASSWDS is not set
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_ADJTIMEX is not set
+# CONFIG_CROND is not set
+# CONFIG_CRONTAB is not set
+# CONFIG_DC is not set
+# CONFIG_DEVFSD is not set
+# CONFIG_LAST is not set
+# CONFIG_HDPARM is not set
+# CONFIG_MAKEDEVS is not set
+# CONFIG_MT is not set
+# CONFIG_RX is not set
+# CONFIG_STRINGS is not set
+# CONFIG_TIME is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_INSMOD=y
+CONFIG_FEATURE_2_4_MODULES=y
+# CONFIG_FEATURE_2_6_MODULES is not set
+CONFIG_FEATURE_INSMOD_VERSION_CHECKING=y
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+CONFIG_LSMOD=y
+CONFIG_FEATURE_QUERY_MODULE_INTERFACE=y
+CONFIG_MODPROBE=y
+CONFIG_RMMOD=y
+CONFIG_FEATURE_CHECK_TAINTED_MODULE=y
+
+#
+# Networking Utilities
+#
+# CONFIG_FEATURE_IPV6 is not set
+# CONFIG_ARPING is not set
+CONFIG_FTPGET=y
+CONFIG_FTPPUT=y
+CONFIG_HOSTNAME=y
+# CONFIG_HTTPD is not set
+CONFIG_IFCONFIG=y
+CONFIG_FEATURE_IFCONFIG_STATUS=y
+# CONFIG_FEATURE_IFCONFIG_SLIP is not set
+# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
+CONFIG_FEATURE_IFCONFIG_HW=y
+# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
+# CONFIG_IFUPDOWN is not set
+# CONFIG_INETD is not set
+# CONFIG_IP is not set
+# CONFIG_IPCALC is not set
+# CONFIG_IPADDR is not set
+# CONFIG_IPLINK is not set
+# CONFIG_IPROUTE is not set
+# CONFIG_IPTUNNEL is not set
+# CONFIG_NAMEIF is not set
+# CONFIG_NC is not set
+CONFIG_NETSTAT=y
+CONFIG_NSLOOKUP=y
+CONFIG_PING=y
+CONFIG_FEATURE_FANCY_PING=y
+CONFIG_ROUTE=y
+# CONFIG_TELNET is not set
+CONFIG_TELNETD=y
+# CONFIG_FEATURE_TELNETD_INETD is not set
+# CONFIG_TFTP is not set
+# CONFIG_TRACEROUTE is not set
+# CONFIG_VCONFIG is not set
+# CONFIG_WGET is not set
+
+#
+# udhcp Server/Client
+#
+# CONFIG_UDHCPD is not set
+# CONFIG_UDHCPC is not set
+
+#
+# Process Utilities
+#
+CONFIG_FREE=y
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+# CONFIG_PIDOF is not set
+CONFIG_PS=y
+# CONFIG_RENICE is not set
+CONFIG_TOP=y
+FEATURE_CPU_USAGE_PERCENTAGE=y
+CONFIG_UPTIME=y
+# CONFIG_SYSCTL is not set
+
+#
+# Another Bourne-like Shell
+#
+CONFIG_FEATURE_SH_IS_ASH=y
+# CONFIG_FEATURE_SH_IS_HUSH is not set
+# CONFIG_FEATURE_SH_IS_LASH is not set
+# CONFIG_FEATURE_SH_IS_MSH is not set
+# CONFIG_FEATURE_SH_IS_NONE is not set
+CONFIG_ASH=y
+
+#
+# Ash Shell Options
+#
+CONFIG_ASH_JOB_CONTROL=y
+CONFIG_ASH_ALIAS=y
+CONFIG_ASH_MATH_SUPPORT=y
+# CONFIG_ASH_MATH_SUPPORT_64 is not set
+# CONFIG_ASH_GETOPTS is not set
+# CONFIG_ASH_CMDCMD is not set
+# CONFIG_ASH_MAIL is not set
+CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
+# CONFIG_ASH_RANDOM_SUPPORT is not set
+# CONFIG_HUSH is not set
+# CONFIG_LASH is not set
+# CONFIG_MSH is not set
+
+#
+# Bourne Shell Options
+#
+# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
+# CONFIG_FEATURE_SH_STANDALONE_SHELL is not set
+CONFIG_FEATURE_COMMAND_EDITING=y
+CONFIG_FEATURE_COMMAND_HISTORY=15
+# CONFIG_FEATURE_COMMAND_SAVEHISTORY is not set
+CONFIG_FEATURE_COMMAND_TAB_COMPLETION=y
+# CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION is not set
+CONFIG_FEATURE_SH_FANCY_PROMPT=y
+
+#
+# System Logging Utilities
+#
+CONFIG_SYSLOGD=y
+# CONFIG_FEATURE_ROTATE_LOGFILE is not set
+# CONFIG_FEATURE_REMOTE_LOG is not set
+# CONFIG_FEATURE_IPC_SYSLOG is not set
+CONFIG_KLOGD=y
+CONFIG_LOGGER=y
+
+#
+# Linux System Utilities
+#
+CONFIG_DMESG=y
+# CONFIG_FBSET is not set
+# CONFIG_FDFLUSH is not set
+# CONFIG_FDFORMAT is not set
+# CONFIG_FDISK is not set
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_GETOPT is not set
+# CONFIG_HEXDUMP is not set
+# CONFIG_HWCLOCK is not set
+# CONFIG_LOSETUP is not set
+# CONFIG_MKSWAP is not set
+CONFIG_MORE=y
+CONFIG_FEATURE_USE_TERMIOS=y
+# CONFIG_PIVOT_ROOT is not set
+# CONFIG_RDATE is not set
+# CONFIG_SWAPONOFF is not set
+CONFIG_MOUNT=y
+CONFIG_NFSMOUNT=y
+CONFIG_UMOUNT=y
+# CONFIG_FEATURE_MOUNT_FORCE is not set
+
+#
+# Common options for mount/umount
+#
+# CONFIG_FEATURE_MOUNT_LOOP is not set
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
diff --git a/busybox/config-dongle-2 b/busybox/config-dongle-2
new file mode 100644 (file)
index 0000000..e1f26b3
--- /dev/null
@@ -0,0 +1,391 @@
+#
+# Automatically generated make config: don't edit
+#
+HAVE_DOT_CONFIG=y
+
+#
+# General Configuration
+#
+# CONFIG_FEATURE_BUFFERS_USE_MALLOC is not set
+CONFIG_FEATURE_BUFFERS_GO_ON_STACK=y
+# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set
+# CONFIG_FEATURE_VERBOSE_USAGE is not set
+# CONFIG_FEATURE_INSTALLER is not set
+# CONFIG_LOCALE_SUPPORT is not set
+# CONFIG_FEATURE_DEVFS is not set
+# CONFIG_FEATURE_DEVPTS is not set
+# CONFIG_FEATURE_CLEAN_UP is not set
+CONFIG_FEATURE_SUID=y
+CONFIG_FEATURE_SUID_CONFIG=y
+CONFIG_FEATURE_SUID_CONFIG_QUIET=y
+# CONFIG_SELINUX is not set
+
+#
+# Build Options
+#
+CONFIG_STATIC=y
+# CONFIG_LFS is not set
+USING_CROSS_COMPILER=y
+CROSS_COMPILER_PREFIX="/opt/crosstool/powerpc-405-linux-gnu/gcc-2.95.3-glibc-2.2.5/bin/powerpc-405-linux-gnu-"
+EXTRA_CFLAGS_OPTIONS=""
+
+#
+# Installation Options
+#
+# CONFIG_INSTALL_NO_USR is not set
+PREFIX="../install"
+
+#
+# Archival Utilities
+#
+# CONFIG_AR is not set
+# CONFIG_BUNZIP2 is not set
+# CONFIG_CPIO is not set
+# CONFIG_DPKG is not set
+# CONFIG_DPKG_DEB is not set
+# CONFIG_GUNZIP is not set
+# CONFIG_GZIP is not set
+# CONFIG_RPM2CPIO is not set
+# CONFIG_RPM is not set
+# CONFIG_TAR is not set
+# CONFIG_UNCOMPRESS is not set
+# CONFIG_UNZIP is not set
+
+#
+# Coreutils
+#
+# CONFIG_BASENAME is not set
+# CONFIG_CAL is not set
+CONFIG_CAT=y
+# CONFIG_CHGRP is not set
+# CONFIG_CHMOD is not set
+# CONFIG_CHOWN is not set
+# CONFIG_CHROOT is not set
+# CONFIG_CMP is not set
+# CONFIG_CP is not set
+# CONFIG_CUT is not set
+CONFIG_DATE=y
+# CONFIG_FEATURE_DATE_ISOFMT is not set
+# CONFIG_DD is not set
+CONFIG_DF=y
+# CONFIG_DIRNAME is not set
+# CONFIG_DOS2UNIX is not set
+CONFIG_DU=y
+CONFIG_FEATURE_DU_DEFALT_BLOCKSIZE_1K=y
+CONFIG_ECHO=y
+CONFIG_FEATURE_FANCY_ECHO=y
+CONFIG_ENV=y
+# CONFIG_EXPR is not set
+CONFIG_FALSE=y
+# CONFIG_FOLD is not set
+# CONFIG_HEAD is not set
+# CONFIG_HOSTID is not set
+CONFIG_ID=y
+# CONFIG_INSTALL is not set
+# CONFIG_LENGTH is not set
+# CONFIG_LN is not set
+# CONFIG_LOGNAME is not set
+CONFIG_LS=y
+CONFIG_FEATURE_LS_FILETYPES=y
+CONFIG_FEATURE_LS_FOLLOWLINKS=y
+# CONFIG_FEATURE_LS_RECURSIVE is not set
+CONFIG_FEATURE_LS_SORTFILES=y
+CONFIG_FEATURE_LS_TIMESTAMPS=y
+CONFIG_FEATURE_LS_USERNAME=y
+CONFIG_FEATURE_LS_COLOR=y
+# CONFIG_MD5SUM is not set
+# CONFIG_MKDIR is not set
+# CONFIG_MKFIFO is not set
+# CONFIG_MKNOD is not set
+# CONFIG_MV is not set
+# CONFIG_OD is not set
+# CONFIG_PRINTF is not set
+CONFIG_PWD=y
+# CONFIG_REALPATH is not set
+# CONFIG_RM is not set
+# CONFIG_RMDIR is not set
+# CONFIG_SEQ is not set
+# CONFIG_SHA1SUM is not set
+# CONFIG_SLEEP is not set
+# CONFIG_SORT is not set
+# CONFIG_STTY is not set
+# CONFIG_SYNC is not set
+# CONFIG_TAIL is not set
+# CONFIG_TEE is not set
+CONFIG_TEST=y
+
+#
+# test (forced enabled for use with shell)
+#
+# CONFIG_FEATURE_TEST_64 is not set
+# CONFIG_TOUCH is not set
+# CONFIG_TR is not set
+CONFIG_TRUE=y
+CONFIG_TTY=y
+CONFIG_UNAME=y
+# CONFIG_UNIQ is not set
+# CONFIG_USLEEP is not set
+# CONFIG_UUDECODE is not set
+# CONFIG_UUENCODE is not set
+# CONFIG_WATCH is not set
+# CONFIG_WC is not set
+# CONFIG_WHO is not set
+CONFIG_WHOAMI=y
+# CONFIG_YES is not set
+
+#
+# Common options for ls and more
+#
+CONFIG_FEATURE_AUTOWIDTH=y
+
+#
+# Common options for df, du, ls
+#
+CONFIG_FEATURE_HUMAN_READABLE=y
+
+#
+# Console Utilities
+#
+# CONFIG_CHVT is not set
+CONFIG_CLEAR=y
+# CONFIG_DEALLOCVT is not set
+# CONFIG_DUMPKMAP is not set
+# CONFIG_LOADFONT is not set
+# CONFIG_LOADKMAP is not set
+# CONFIG_OPENVT is not set
+CONFIG_RESET=y
+# CONFIG_SETKEYCODES is not set
+
+#
+# Debian Utilities
+#
+# CONFIG_MKTEMP is not set
+# CONFIG_PIPE_PROGRESS is not set
+# CONFIG_READLINK is not set
+# CONFIG_RUN_PARTS is not set
+# CONFIG_START_STOP_DAEMON is not set
+# CONFIG_WHICH is not set
+
+#
+# Editors
+#
+# CONFIG_AWK is not set
+# CONFIG_PATCH is not set
+# CONFIG_SED is not set
+# CONFIG_VI is not set
+
+#
+# Finding Utilities
+#
+# CONFIG_FIND is not set
+# CONFIG_GREP is not set
+# CONFIG_XARGS is not set
+
+#
+# Init Utilities
+#
+CONFIG_INIT=y
+CONFIG_FEATURE_USE_INITTAB=y
+CONFIG_FEATURE_INITRD=y
+# CONFIG_FEATURE_INIT_COREDUMPS is not set
+CONFIG_FEATURE_EXTRA_QUIET=y
+# CONFIG_HALT is not set
+# CONFIG_POWEROFF is not set
+CONFIG_REBOOT=y
+# CONFIG_MESG is not set
+
+#
+# Login/Password Management Utilities
+#
+CONFIG_USE_BB_PWD_GRP=y
+# CONFIG_ADDGROUP is not set
+# CONFIG_DELGROUP is not set
+# CONFIG_ADDUSER is not set
+# CONFIG_DELUSER is not set
+# CONFIG_GETTY is not set
+# CONFIG_FEATURE_U_W_TMP is not set
+CONFIG_LOGIN=y
+CONFIG_FEATURE_SECURETTY=y
+# CONFIG_PASSWD is not set
+# CONFIG_SU is not set
+# CONFIG_SULOGIN is not set
+# CONFIG_VLOCK is not set
+
+#
+# Common options for adduser, deluser, login, su
+#
+# CONFIG_FEATURE_SHADOWPASSWDS is not set
+
+#
+# Miscellaneous Utilities
+#
+# CONFIG_ADJTIMEX is not set
+# CONFIG_CROND is not set
+# CONFIG_CRONTAB is not set
+# CONFIG_DC is not set
+# CONFIG_DEVFSD is not set
+# CONFIG_LAST is not set
+# CONFIG_HDPARM is not set
+# CONFIG_MAKEDEVS is not set
+# CONFIG_MT is not set
+# CONFIG_RX is not set
+# CONFIG_STRINGS is not set
+# CONFIG_TIME is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Linux Module Utilities
+#
+CONFIG_INSMOD=y
+CONFIG_FEATURE_2_4_MODULES=y
+# CONFIG_FEATURE_2_6_MODULES is not set
+CONFIG_FEATURE_INSMOD_VERSION_CHECKING=y
+# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set
+# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set
+# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set
+CONFIG_LSMOD=y
+CONFIG_FEATURE_QUERY_MODULE_INTERFACE=y
+CONFIG_MODPROBE=y
+CONFIG_RMMOD=y
+CONFIG_FEATURE_CHECK_TAINTED_MODULE=y
+
+#
+# Networking Utilities
+#
+# CONFIG_FEATURE_IPV6 is not set
+# CONFIG_ARPING is not set
+# CONFIG_FTPGET is not set
+# CONFIG_FTPPUT is not set
+CONFIG_HOSTNAME=y
+# CONFIG_HTTPD is not set
+CONFIG_IFCONFIG=y
+CONFIG_FEATURE_IFCONFIG_STATUS=y
+# CONFIG_FEATURE_IFCONFIG_SLIP is not set
+# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set
+CONFIG_FEATURE_IFCONFIG_HW=y
+# CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS is not set
+# CONFIG_IFUPDOWN is not set
+# CONFIG_INETD is not set
+# CONFIG_IP is not set
+# CONFIG_IPCALC is not set
+# CONFIG_IPADDR is not set
+# CONFIG_IPLINK is not set
+# CONFIG_IPROUTE is not set
+# CONFIG_IPTUNNEL is not set
+# CONFIG_NAMEIF is not set
+# CONFIG_NC is not set
+CONFIG_NETSTAT=y
+# CONFIG_NSLOOKUP is not set
+CONFIG_PING=y
+CONFIG_FEATURE_FANCY_PING=y
+CONFIG_ROUTE=y
+# CONFIG_TELNET is not set
+CONFIG_TELNETD=y
+# CONFIG_FEATURE_TELNETD_INETD is not set
+# CONFIG_TFTP is not set
+# CONFIG_TRACEROUTE is not set
+# CONFIG_VCONFIG is not set
+# CONFIG_WGET is not set
+
+#
+# udhcp Server/Client
+#
+# CONFIG_UDHCPD is not set
+# CONFIG_UDHCPC is not set
+
+#
+# Process Utilities
+#
+CONFIG_FREE=y
+CONFIG_KILL=y
+CONFIG_KILLALL=y
+# CONFIG_PIDOF is not set
+CONFIG_PS=y
+# CONFIG_RENICE is not set
+CONFIG_TOP=y
+FEATURE_CPU_USAGE_PERCENTAGE=y
+CONFIG_UPTIME=y
+# CONFIG_SYSCTL is not set
+
+#
+# Another Bourne-like Shell
+#
+CONFIG_FEATURE_SH_IS_ASH=y
+# CONFIG_FEATURE_SH_IS_HUSH is not set
+# CONFIG_FEATURE_SH_IS_LASH is not set
+# CONFIG_FEATURE_SH_IS_MSH is not set
+# CONFIG_FEATURE_SH_IS_NONE is not set
+CONFIG_ASH=y
+
+#
+# Ash Shell Options
+#
+CONFIG_ASH_JOB_CONTROL=y
+# CONFIG_ASH_ALIAS is not set
+# CONFIG_ASH_MATH_SUPPORT is not set
+# CONFIG_ASH_GETOPTS is not set
+# CONFIG_ASH_CMDCMD is not set
+# CONFIG_ASH_MAIL is not set
+CONFIG_ASH_OPTIMIZE_FOR_SIZE=y
+# CONFIG_ASH_RANDOM_SUPPORT is not set
+# CONFIG_HUSH is not set
+# CONFIG_LASH is not set
+# CONFIG_MSH is not set
+
+#
+# Bourne Shell Options
+#
+# CONFIG_FEATURE_SH_EXTRA_QUIET is not set
+# CONFIG_FEATURE_SH_STANDALONE_SHELL is not set
+CONFIG_FEATURE_COMMAND_EDITING=y
+CONFIG_FEATURE_COMMAND_HISTORY=15
+# CONFIG_FEATURE_COMMAND_SAVEHISTORY is not set
+CONFIG_FEATURE_COMMAND_TAB_COMPLETION=y
+# CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION is not set
+CONFIG_FEATURE_SH_FANCY_PROMPT=y
+
+#
+# System Logging Utilities
+#
+CONFIG_SYSLOGD=y
+# CONFIG_FEATURE_ROTATE_LOGFILE is not set
+CONFIG_FEATURE_REMOTE_LOG=y
+# CONFIG_FEATURE_IPC_SYSLOG is not set
+CONFIG_KLOGD=y
+CONFIG_LOGGER=y
+
+#
+# Linux System Utilities
+#
+CONFIG_DMESG=y
+# CONFIG_FBSET is not set
+# CONFIG_FDFLUSH is not set
+# CONFIG_FDFORMAT is not set
+# CONFIG_FDISK is not set
+# CONFIG_FREERAMDISK is not set
+# CONFIG_FSCK_MINIX is not set
+# CONFIG_MKFS_MINIX is not set
+# CONFIG_GETOPT is not set
+# CONFIG_HEXDUMP is not set
+# CONFIG_HWCLOCK is not set
+# CONFIG_LOSETUP is not set
+# CONFIG_MKSWAP is not set
+# CONFIG_MORE is not set
+# CONFIG_PIVOT_ROOT is not set
+# CONFIG_RDATE is not set
+# CONFIG_SWAPONOFF is not set
+CONFIG_MOUNT=y
+# CONFIG_NFSMOUNT is not set
+CONFIG_UMOUNT=y
+# CONFIG_FEATURE_MOUNT_FORCE is not set
+
+#
+# Common options for mount/umount
+#
+# CONFIG_FEATURE_MOUNT_LOOP is not set
+# CONFIG_FEATURE_MTAB_SUPPORT is not set
+
+#
+# Debugging Options
+#
+# CONFIG_DEBUG is not set
diff --git a/busybox/fullclean b/busybox/fullclean
new file mode 100755 (executable)
index 0000000..52109d7
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+rm -rf dev dongle
diff --git a/busybox/prepare b/busybox/prepare
new file mode 100755 (executable)
index 0000000..91b7f33
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+mkdir $1
+cd $1
+tar -jxvf ../../packages/busybox-1.00.tar.bz2
+
diff --git a/crosstool/README b/crosstool/README
new file mode 100644 (file)
index 0000000..b96c06f
--- /dev/null
@@ -0,0 +1,5 @@
+autobuild   - does full clean, unpacks crosstool and runs build
+prepare     - unpacks the crosstool sources
+build       - uses crosstool to build a compiler
+clean       - removes everything except files downloaded by crosstool
+fullclean   - removes everything
diff --git a/crosstool/autobuild b/crosstool/autobuild
new file mode 100755 (executable)
index 0000000..0661f16
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+./fullclean
+./prepare
+./build
diff --git a/crosstool/build b/crosstool/build
new file mode 100755 (executable)
index 0000000..b3a51d1
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+# Adapted from the demo-powerpc-405 script in crosstool
+
+set -ex
+TARBALLS_DIR=`pwd`/downloads
+RESULT_TOP=`pwd`
+export TARBALLS_DIR RESULT_TOP
+GCC_LANGUAGES="c,c++"
+export GCC_LANGUAGES
+
+cd crosstool-0.43
+eval `cat powerpc-405.dat gcc-3.4.5-glibc-2.2.5.dat` sh all.sh --notest
+cd ..
+
+echo export CROSS=`pwd`/gcc-3.4.5-glibc-2.2.5/powerpc-405-linux-gnu/bin/powerpc-405-linux-gnu- > cross-var
+
+echo Done.
diff --git a/crosstool/clean b/crosstool/clean
new file mode 100755 (executable)
index 0000000..aac4ae2
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+rm -rf cross-var crosstool-0.43 gcc-3.4.5-glibc-2.2.5
diff --git a/crosstool/fullclean b/crosstool/fullclean
new file mode 100755 (executable)
index 0000000..038828c
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+rm -rf cross-var crosstool-0.43 gcc-3.4.5-glibc-2.2.5 downloads
+
diff --git a/crosstool/glibc-2.2.5-allow-gcc-4.0-configure.patch b/crosstool/glibc-2.2.5-allow-gcc-4.0-configure.patch
new file mode 100644 (file)
index 0000000..6549cd1
--- /dev/null
@@ -0,0 +1,22 @@
+Fixes\r
+checking version of powerpc-405-linux-gnu-gcc ... 4.0.0, bad\r
+checking for gnumake... no\r
+checking for gmake... no\r
+checking for make... make\r
+checking version of make... 3.80, ok\r
+configure: error:\r
+*** These critical programs are missing or too old:gcc \r
+\r
+\r
+--- glibc-2.2.5/configure.old  2005-03-10 00:23:46.374213600 -0800\r
++++ glibc-2.2.5/configure      2005-03-10 00:25:13.313996744 -0800\r
+@@ -1476,7 +1476,7 @@\r
+   ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version \([egcygnustpi-]*[0-9.]*\).*$/\1/p'`\r
+   case $ac_prog_version in\r
+     '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;\r
+-    *gcc-2.9[5-9].*|*2.8.[1-9]*|*2.9|*2.9.[0-9]*|2.9[5-9]*|3.[0-9]*|cygnus-2.9[1-9]*|gcc-2.9[5-9]|gcc-2.1[0-9][0-9]|sgicc-*)\r
++    *gcc-2.9[5-9].*|*2.8.[1-9]*|*2.9|*2.9.[0-9]*|2.9[5-9]*|3.[0-9]*|4.[01234]*|cygnus-2.9[1-9]*|gcc-2.9[5-9]|gcc-2.1[0-9][0-9]|sgicc-*)\r
+        ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;\r
+     *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;\r
\r
+\r
diff --git a/crosstool/prepare b/crosstool/prepare
new file mode 100755 (executable)
index 0000000..f7d81d6
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+# Avoid downloading from GNU
+mkdir downloads
+ln -s ../../packages/binutils-2.15.tar.bz2 downloads
+ln -s ../../packages/glibc-2.2.5.tar.gz downloads
+ln -s ../../packages/linux-2.6.8.tar.bz2 downloads
+ln -s ../../packages/gcc-3.4.5.tar.bz2 downloads
+ln -s ../../packages/glibc-linuxthreads-2.2.5.tar.gz downloads
+
+tar -zxvf ../packages/crosstool-0.43.tar.gz
+rm -fv crosstool-0.43/patches/glibc-2.2.5/glibc-2.2.5-allow-gcc-4.0-configure.patch
+cp -v glibc-2.2.5-allow-gcc-4.0-configure.patch crosstool-0.43/patches/glibc-2.2.5
diff --git a/dongle/README b/dongle/README
new file mode 100644 (file)
index 0000000..0ceaa25
--- /dev/null
@@ -0,0 +1,4 @@
+autobuild   - does fullclean, prepare, build
+prepare     - sets up genext2fs
+build       - builds the dongle
+fullclean   - removes temporary build files, genext2fs and the dongle
diff --git a/dongle/autobuild b/dongle/autobuild
new file mode 100755 (executable)
index 0000000..a716723
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+./fullclean
+./prepare
+./build
diff --git a/dongle/build b/dongle/build
new file mode 100755 (executable)
index 0000000..8daa9c0
--- /dev/null
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+. ../crosstool/cross-var
+
+LKERN=../kernel/dongle/linux-2.4.31
+LGENFS=genext2fs-1.4/genext2fs
+OUTFILE=vomp-dongle
+
+# Create initial file system
+
+cp -a ../busybox/dongle/install fs
+cp -a tofs/* fs
+
+# Insert vompclient
+
+cp -fv ../client/vompclient fs
+cp -fv ../client/other/*.jpg fs
+cp -fv ../lbox_border/lbox_border.o fs/lib/modules/2.4.31
+
+# Get kernel files temp dir ready
+
+mkdir kernel_temp
+BOOT=${LKERN}/arch/ppc/boot
+CFILES=${BOOT}/common/{dummy,misc-common,ns16550,relocate,string,util,serial_stub}.o
+SFILES=${BOOT}/simple/{embed_config,head,misc-embedded}.o
+KFILE=${BOOT}/images/vmlinux.gz
+FILES=`sh -c "echo $CFILES $SFILES $KFILE ${BOOT}/lib/zlib.a ${BOOT}/ld.script"`
+cp $FILES kernel_temp
+
+# Check filesystem size
+
+RAMDISK_SIZE=`du -ks fs | cut -f 1`
+let RAMDISK_SIZE=$RAMDISK_SIZE+300
+if [ $RAMDISK_SIZE -gt 4096 ] ; then
+  echo "ramdisk too big"
+  exit
+fi
+
+# Create the ramdisk out of the fs directory
+
+${LGENFS} -d fs -b ${RAMDISK_SIZE} -D devtable ramdisk
+/bin/gzip ramdisk
+
+# Put it all together
+
+mkdir build_temp
+
+# make_dongle() - this is straight out of arch/ppc in the linux tree
+
+OBJCOPY=${CROSS}objcopy
+LD=${CROSS}ld
+
+$OBJCOPY -O elf32-powerpc \
+  --add-section=.ramdisk=ramdisk.gz \
+  --set-section-flags=.ramdisk=contents,alloc,load,readonly,data \
+  --add-section=.image=kernel_temp/vmlinux.gz \
+  --set-section-flags=.image=contents,alloc,load,readonly,data \
+  kernel_temp/dummy.o build_temp/image.o
+
+$LD -T kernel_temp/ld.script -Ttext 0x00400000 -Bstatic -o build_temp/zvmlinux.initrd \
+  kernel_temp/head.o kernel_temp/relocate.o kernel_temp/misc-embedded.o \
+  kernel_temp/misc-common.o kernel_temp/string.o kernel_temp/util.o kernel_temp/serial_stub.o \
+  kernel_temp/embed_config.o kernel_temp/ns16550.o build_temp/image.o \
+  kernel_temp/zlib.a
+
+$OBJCOPY -O elf32-powerpc build_temp/zvmlinux.initrd build_temp/zvmlinux.initrd \
+  -R .comment -R .stab -R .stabstr -R .sysmap
+
+${LKERN}/arch/ppc/boot/utils/mktree build_temp/zvmlinux.initrd $OUTFILE
+
+# Clean up
+
+rm -f ramdisk.gz
+rm -rf build_temp
+rm -rf kernel_temp
+rm -rf fs
+
+# Install to tftp location
+
+if [ -d /diskless/tftp/mvp ] && [ -w /diskless/tftp/mvp ]
+then
+  cp -v $OUTFILE /diskless/tftp/mvp
+fi
+
+if [ -d /diskless/tftp/wmvp ] && [ -w /diskless/tftp/wmvp ]
+then
+  cp -v $OUTFILE /diskless/tftp/wmvp
+fi
diff --git a/dongle/devtable b/dongle/devtable
new file mode 100644 (file)
index 0000000..e95f950
--- /dev/null
@@ -0,0 +1,48 @@
+# name type mode uid gid major minor start inc count
+
+/dev/adec_ac3      c   600  0  0  202   1  0  0
+/dev/adec_dev      c   600  0  0  202   0  0  0
+/dev/adec_mixer    c   600  0  0  202   3  0  0
+/dev/adec_mpg      c   600  0  0  202   0  0  0
+/dev/adec_pcm      c   600  0  0  202   2  0  0
+/dev/aud_mpeg      c   600  0  0  202   0  0  0
+/dev/console       c   600  0  0    5   1  0  0
+/dev/fb0           c   600  0  0   29   0  0  0
+/dev/fb1           c   600  0  0   29   1  0  0
+/dev/full          c   600  0  0    1   7  0  0
+/dev/irmouse       c   600  0  0   10  11  0  0
+/dev/kmem          c   600  0  0    1   2  0  0
+/dev/mem           c   600  0  0    1   1  0  0
+/dev/mtd0          c   600  0  0   90   0  0  0
+/dev/mtd1          c   600  0  0   90   2  0  0
+/dev/mtd2          c   600  0  0   90   4  0  0
+/dev/mtd3          c   600  0  0   90   6  0  0
+/dev/mtd4          c   600  0  0   90   8  0  0
+/dev/mtdblock0     b   600  0  0   31   0  0  0
+/dev/mtdblock1     b   600  0  0   31   1  0  0
+/dev/null          c   600  0  0    1   3  0  0
+/dev/port          c   600  0  0    1   4  0  0
+/dev/ptyp0         c   600  0  0    2   0  0  0
+/dev/ptyp1         c   600  0  0    2   1  0  0
+/dev/ptyp2         c   600  0  0    2   2  0  0
+/dev/ptyp3         c   600  0  0    2   3  0  0
+/dev/ptyp4         c   600  0  0    2   4  0  0
+/dev/ram0          b   600  0  0    1   0  0  0
+/dev/ram1          b   600  0  0    1   1  0  0
+/dev/ram2          b   600  0  0    1   2  0  0
+/dev/random        c   600  0  0    1   8  0  0
+/dev/rawir         c   600  0  0  100   0  0  0
+/dev/stbgfx        c   600  0  0  251   0  0  0
+/dev/tty           c   600  0  0    5   0  0  0
+/dev/tty0          c   600  0  0    4   0  0  0
+/dev/tty5          c   600  0  0    4   5  0  0
+/dev/ttyS0         c   600  0  0    4  64  0  0
+/dev/ttyp0         c   600  0  0    3   0  0  0
+/dev/ttyp1         c   600  0  0    3   1  0  0
+/dev/ttyp2         c   600  0  0    3   2  0  0
+/dev/ttyp3         c   600  0  0    3   3  0  0
+/dev/urandom       c   600  0  0    1   9  0  0
+/dev/vdec_dev      c   600  0  0  203   0  0  0
+/dev/vid           c   600  0  0  203   0  0  0
+/dev/xram          c   600  0  0   63   0  0  0
+/dev/zero          c   600  0  0    1   5  0  0
diff --git a/dongle/fullclean b/dongle/fullclean
new file mode 100755 (executable)
index 0000000..0ff07bb
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+rm -rf ramdisk.gz build_temp kernel_temp fs vomp-dongle genext2fs-1.4
+
diff --git a/dongle/prepare b/dongle/prepare
new file mode 100755 (executable)
index 0000000..5a7e056
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+tar -zxvf ../packages/genext2fs-1.4.tar.gz
+cd genext2fs-1.4
+./configure
+make
diff --git a/dongle/tofs/dev/fb b/dongle/tofs/dev/fb
new file mode 120000 (symlink)
index 0000000..2d66930
--- /dev/null
@@ -0,0 +1 @@
+fb0
\ No newline at end of file
diff --git a/dongle/tofs/dev/kcore b/dongle/tofs/dev/kcore
new file mode 120000 (symlink)
index 0000000..d920e94
--- /dev/null
@@ -0,0 +1 @@
+../proc/kcore
\ No newline at end of file
diff --git a/dongle/tofs/dev/mouse b/dongle/tofs/dev/mouse
new file mode 120000 (symlink)
index 0000000..3d81984
--- /dev/null
@@ -0,0 +1 @@
+irmouse
\ No newline at end of file
diff --git a/dongle/tofs/dev/ram b/dongle/tofs/dev/ram
new file mode 120000 (symlink)
index 0000000..5f76aa2
--- /dev/null
@@ -0,0 +1 @@
+ram1
\ No newline at end of file
diff --git a/dongle/tofs/dev/ramdisk b/dongle/tofs/dev/ramdisk
new file mode 120000 (symlink)
index 0000000..b5b544a
--- /dev/null
@@ -0,0 +1 @@
+ram0
\ No newline at end of file
diff --git a/dongle/tofs/dev/stderr b/dongle/tofs/dev/stderr
new file mode 120000 (symlink)
index 0000000..c67586e
--- /dev/null
@@ -0,0 +1 @@
+../proc/self/fd/2
\ No newline at end of file
diff --git a/dongle/tofs/dev/stdin b/dongle/tofs/dev/stdin
new file mode 120000 (symlink)
index 0000000..2825dc0
--- /dev/null
@@ -0,0 +1 @@
+../proc/self/fd/0
\ No newline at end of file
diff --git a/dongle/tofs/dev/stdout b/dongle/tofs/dev/stdout
new file mode 120000 (symlink)
index 0000000..35e0f62
--- /dev/null
@@ -0,0 +1 @@
+../proc/self/fd/1
\ No newline at end of file
diff --git a/dongle/tofs/etc/fstab b/dongle/tofs/etc/fstab
new file mode 100644 (file)
index 0000000..e87aabc
--- /dev/null
@@ -0,0 +1 @@
+/proc           /proc   proc    defaults        0       0
diff --git a/dongle/tofs/etc/group b/dongle/tofs/etc/group
new file mode 100644 (file)
index 0000000..39dbbc7
--- /dev/null
@@ -0,0 +1 @@
+root::0:
diff --git a/dongle/tofs/etc/hosts b/dongle/tofs/etc/hosts
new file mode 100644 (file)
index 0000000..d0bdd91
--- /dev/null
@@ -0,0 +1 @@
+127.0.0.1      localhost       localhost
diff --git a/dongle/tofs/etc/inittab b/dongle/tofs/etc/inittab
new file mode 100644 (file)
index 0000000..cad6a5b
--- /dev/null
@@ -0,0 +1,2 @@
+::sysinit:/etc/rcS
+::restart:/sbin/init
diff --git a/dongle/tofs/etc/issue.net b/dongle/tofs/etc/issue.net
new file mode 100644 (file)
index 0000000..1418336
--- /dev/null
@@ -0,0 +1,3 @@
+VOMP Client
+
+
diff --git a/dongle/tofs/etc/passwd b/dongle/tofs/etc/passwd
new file mode 100644 (file)
index 0000000..233d68f
--- /dev/null
@@ -0,0 +1 @@
+root::0:0:root:/:/bin/sh
diff --git a/dongle/tofs/etc/profile b/dongle/tofs/etc/profile
new file mode 100644 (file)
index 0000000..9a39bd1
--- /dev/null
@@ -0,0 +1,13 @@
+
+# default timezone
+#TZ=CST+6CDT,M4.1.0/2,M10.5.0/2
+#export TZ
+
+# if shell.config exist then source it.
+# shell.config should be created by dongle.config
+# eg: to set timezone to EST
+# echo "TZ=EST+5EDT,M4.1.0/2,M10.5.0/2; export TZ" > /etc/shell.config
+#
+#if [ -r /etc/shell.config ]; then
+#   . /etc/shell.config
+#fi   
diff --git a/dongle/tofs/etc/rcS b/dongle/tofs/etc/rcS
new file mode 100755 (executable)
index 0000000..e419989
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# Mount everything in /etc/fstab
+#
+/bin/umount -a
+/bin/mount -a -o rw
+
+#
+# Configure lo0
+# eth0 will be autoconfigured by the kernel
+#
+/sbin/ifconfig lo 127.0.0.1
+
+#
+# Start telnetd
+#
+/usr/sbin/telnetd
+
+#
+# Load kernel modules
+#
+insmod -f os_core
+insmod -f av_core _fmt=1
+insmod -f ircombo
+insmod -f gfx
+insmod -f osdfb
+#insmod ac3_mod
+#insmod xrmod
+insmod lbox_border
+
+#udhcpc
+#. /etc/udhcpc.config
+
+/vompclient
diff --git a/dongle/tofs/lib/modules/2.4.31/av_core.o b/dongle/tofs/lib/modules/2.4.31/av_core.o
new file mode 100644 (file)
index 0000000..fecb73a
Binary files /dev/null and b/dongle/tofs/lib/modules/2.4.31/av_core.o differ
diff --git a/dongle/tofs/lib/modules/2.4.31/gfx.o b/dongle/tofs/lib/modules/2.4.31/gfx.o
new file mode 100644 (file)
index 0000000..20dc54d
Binary files /dev/null and b/dongle/tofs/lib/modules/2.4.31/gfx.o differ
diff --git a/dongle/tofs/lib/modules/2.4.31/ircombo.o b/dongle/tofs/lib/modules/2.4.31/ircombo.o
new file mode 100644 (file)
index 0000000..247f873
Binary files /dev/null and b/dongle/tofs/lib/modules/2.4.31/ircombo.o differ
diff --git a/dongle/tofs/lib/modules/2.4.31/os_core.o b/dongle/tofs/lib/modules/2.4.31/os_core.o
new file mode 100644 (file)
index 0000000..6b977d2
Binary files /dev/null and b/dongle/tofs/lib/modules/2.4.31/os_core.o differ
diff --git a/dongle/tofs/lib/modules/2.4.31/osdfb.o b/dongle/tofs/lib/modules/2.4.31/osdfb.o
new file mode 100644 (file)
index 0000000..b50bdf0
Binary files /dev/null and b/dongle/tofs/lib/modules/2.4.31/osdfb.o differ
diff --git a/jpeg/README b/jpeg/README
new file mode 100644 (file)
index 0000000..452a106
--- /dev/null
@@ -0,0 +1,6 @@
+
+autobuild - runs fullclean, prepare, build
+prepare   - unpacks the jpeg library sources
+build     - builds the jpeg library
+clean     - cleans the jpeg library source tree
+fullclean - removes the jpeg library source tree
diff --git a/jpeg/autobuild b/jpeg/autobuild
new file mode 100755 (executable)
index 0000000..a716723
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+./fullclean
+./prepare
+./build
diff --git a/jpeg/build b/jpeg/build
new file mode 100755 (executable)
index 0000000..c8dec8e
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+. ../crosstool/cross-var
+
+export CC=${CROSS}gcc
+export AR=${CROSS}ar
+export RANLIB=${CROSS}ranlib
+
+cd jpeg-6b
+./configure
+make
diff --git a/jpeg/clean b/jpeg/clean
new file mode 100755 (executable)
index 0000000..8a1e717
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+cd jpeg-6b
+make distclean
diff --git a/jpeg/fullclean b/jpeg/fullclean
new file mode 100755 (executable)
index 0000000..59725dd
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+rm -rf jpeg-6b
diff --git a/jpeg/prepare b/jpeg/prepare
new file mode 100755 (executable)
index 0000000..07e4d1e
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+tar -zxvf ../packages/jpegsrc.v6b.tar.gz
diff --git a/kernel/README b/kernel/README
new file mode 100644 (file)
index 0000000..299ad9d
--- /dev/null
@@ -0,0 +1,15 @@
+$1 argument to scripts that have it should be dev or dongle, see autobuild
+for examples.
+
+autobuild   - does full clean then full build
+prepare $1  - unpacks kernel tree into $1 dir and runs patch on it
+              only to be used after fullclean (or just un-tarred package)
+patch $1    - applies patches to kernel under $1 dir
+build $1 $2 - work with kernel under $1 dir. copy config file $2 to kernel
+              and compile kernel
+              only to be used on a cleaned and patched kernel tree
+clean $1    - runs make mrproper on kernel tree in dir $1
+              makes it ready for build
+fullclean   - removes kernel trees in order to start from scratch
+
+
diff --git a/kernel/autobuild b/kernel/autobuild
new file mode 100755 (executable)
index 0000000..60ec99f
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+./fullclean
+
+./prepare dev
+./prepare dongle
+
+./build dev config-dev-5
+./build dongle config-dongle-2
+
diff --git a/kernel/build b/kernel/build
new file mode 100755 (executable)
index 0000000..b450f2a
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+. ../crosstool/cross-var
+
+export ARCH=ppc
+export CROSS_COMPILE=${CROSS}
+export EXTRAVERSION=-v1.1-hcwmvp
+
+cd $1/linux-2.4.31
+cp ../../$2 .config
+make oldconfig
+make dep
+make zImage
diff --git a/kernel/clean b/kernel/clean
new file mode 100755 (executable)
index 0000000..1b78e73
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+cd $1/linux-2.4.31
+make mrproper
diff --git a/kernel/config-dev-5 b/kernel/config-dev-5
new file mode 100644 (file)
index 0000000..a7bc12f
--- /dev/null
@@ -0,0 +1,682 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_4xx=y
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_REDWOOD_5 is not set
+CONFIG_REDWOOD_6=y
+# CONFIG_OAK is not set
+# CONFIG_WALNUT is not set
+CONFIG_HCW_MVP=y
+# CONFIG_SMP is not set
+CONFIG_KEXEC=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_STB03xxx=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_405=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM405_ERR77=y
+CONFIG_PPC4xx_DMA=y
+CONFIG_STBXXX_DMA=y
+CONFIG_IBM_OPENBIOS=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_PPC_RTC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600 profile=3 root=/dev/nfs ip=:::::eth0:dhcp"
+
+#
+# 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=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_RAM=y
+# 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_TQM8XXL is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_MBX860 is not set
+# CONFIG_MTD_DBOX2 is not set
+# CONFIG_MTD_CFI_FLAGADM is not set
+CONFIG_MTD_REDWOOD=y
+CONFIG_MTD_MVP_RAM=y
+# 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
+# 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
+
+#
+# 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 is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_INET_ECN is not set
+CONFIG_SYN_COOKIES=y
+# 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
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI 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_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_OAKNET 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=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+# CONFIG_SMC9194 is not set
+CONFIG_SMC91111=y
+CONFIG_SMC91111_ADVANCED=y
+CONFIG_SMC91111_BYTE_SWAP=y
+# CONFIG_SMC91111_USE_8_BIT is not set
+# CONFIG_SMC91111_USE_32_BIT 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
+
+#
+# On-chip net devices
+#
+# CONFIG_IBM_OCP_ENET 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
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 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=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+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 is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# 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
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+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=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_PPC405_ALGO is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_PROC=y
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_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 is not set
+# 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 is not set
+# CONFIG_W83877F_WDT is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_MACHZ_WDT is not set
+CONFIG_PPC405_WDT=y
+# 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
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_PROC_FS is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS 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
+
+#
+# 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 is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 is not set
+# 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 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 is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff --git a/kernel/config-dongle-2 b/kernel/config-dongle-2
new file mode 100644 (file)
index 0000000..dee2c02
--- /dev/null
@@ -0,0 +1,684 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_PPC32=y
+# CONFIG_6xx is not set
+CONFIG_40x=y
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_4xx=y
+# CONFIG_CPCI405 is not set
+# CONFIG_EP405 is not set
+# CONFIG_REDWOOD_5 is not set
+CONFIG_REDWOOD_6=y
+# CONFIG_OAK is not set
+# CONFIG_WALNUT is not set
+CONFIG_HCW_MVP=y
+# CONFIG_SMP is not set
+CONFIG_KEXEC=y
+# CONFIG_MATH_EMULATION is not set
+CONFIG_NOT_COHERENT_CACHE=y
+CONFIG_UART0_TTYS0=y
+# CONFIG_UART0_TTYS1 is not set
+CONFIG_STB03xxx=y
+CONFIG_IBM_OCP=y
+CONFIG_PPC_OCP=y
+CONFIG_405=y
+CONFIG_IBM405_ERR51=y
+CONFIG_IBM405_ERR77=y
+CONFIG_PPC4xx_DMA=y
+CONFIG_STBXXX_DMA=y
+CONFIG_IBM_OPENBIOS=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI is not set
+# CONFIG_PC_KEYBOARD is not set
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_OOM_KILLER is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_PPC_RTC is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600 ip=:::::eth0:dhcp root=/dev/ram0"
+
+#
+# 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 is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# 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 is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA 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=y
+CONFIG_MTD_AMDSTD=y
+# 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_TQM8XXL is not set
+# CONFIG_MTD_RPXLITE is not set
+# CONFIG_MTD_MBX860 is not set
+# CONFIG_MTD_DBOX2 is not set
+# CONFIG_MTD_CFI_FLAGADM is not set
+CONFIG_MTD_REDWOOD=y
+# CONFIG_MTD_MVP_RAM 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
+# 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
+
+#
+# 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=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# 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 is not set
+# CONFIG_FILTER is not set
+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=y
+# CONFIG_IP_PNP_BOOTP is not set
+# 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=y
+# 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
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI 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_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+# CONFIG_OAKNET 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=y
+# CONFIG_WD80x3 is not set
+# CONFIG_ULTRAMCA is not set
+# CONFIG_ULTRA is not set
+# CONFIG_ULTRA32 is not set
+# CONFIG_SMC9194 is not set
+CONFIG_SMC91111=y
+CONFIG_SMC91111_ADVANCED=y
+CONFIG_SMC91111_BYTE_SWAP=y
+# CONFIG_SMC91111_USE_8_BIT is not set
+# CONFIG_SMC91111_USE_32_BIT 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
+
+#
+# On-chip net devices
+#
+# CONFIG_IBM_OCP_ENET 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
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_OF is not set
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA16 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=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+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 is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# 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
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+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=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_PPC405_ALGO is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_PROC=y
+
+#
+# Mice
+#
+CONFIG_BUSMOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
+# CONFIG_MS_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 is not set
+# 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 is not set
+# CONFIG_W83877F_WDT is not set
+# CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_MACHZ_WDT is not set
+CONFIG_PPC405_WDT=y
+# 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
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+
+#
+# Video For Linux
+#
+# CONFIG_VIDEO_PROC_FS is not set
+# CONFIG_I2C_PARPORT is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_VIDEO_PMS 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
+
+#
+# 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 is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BEFS_DEBUG is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# 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 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 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 is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC32 is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=0
diff --git a/kernel/fullclean b/kernel/fullclean
new file mode 100755 (executable)
index 0000000..52109d7
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+rm -rf dev dongle
diff --git a/kernel/otherpatches/Makefile.patch b/kernel/otherpatches/Makefile.patch
new file mode 100644 (file)
index 0000000..548f419
--- /dev/null
@@ -0,0 +1,14 @@
+diff -Naur linux-2.4.31-orig/Makefile linux-2.4.31/Makefile
+--- linux-2.4.31-orig/Makefile 2007-01-26 23:52:46.000000000 +0000
++++ linux-2.4.31/Makefile      2007-01-26 23:53:13.000000000 +0000
+@@ -21,8 +21,8 @@
+ #CROSS_COMPILE        =
+-ARCH=ppc
+-CROSS_COMPILE = powerpc-405-linux-gnu-
++#ARCH=ppc
++#CROSS_COMPILE        = powerpc-405-linux-gnu-
+ #
+ # Include the make variables (CC, etc...)
diff --git a/kernel/otherpatches/bash4_correction.patch b/kernel/otherpatches/bash4_correction.patch
new file mode 100644 (file)
index 0000000..31ad563
--- /dev/null
@@ -0,0 +1,17 @@
+diff -Naur linux-2.4.31.orig/scripts/Configure linux-2.4.31/scripts/Configure
+--- linux-2.4.31.orig/scripts/Configure        2005-04-04 03:42:20.000000000 +0200
++++ linux-2.4.31/scripts/Configure     2011-11-01 12:37:25.000000000 +0100
+@@ -546,10 +546,10 @@
+   echo "#"
+   echo "# Using defaults found in" $DEFAULTS
+   echo "#"
+-  . $DEFAULTS
++  . `pwd`/$DEFAULTS
+   sed -e 's/# \(CONFIG_[^ ]*\) is not.*/\1=n/' <$DEFAULTS >.config-is-not.$$
+-  . .config-is-not.$$
+-  rm .config-is-not.$$
++  . `pwd`/.config-is-not.$$
++  rm `pwd`/.config-is-not.$$
+ else
+   echo "#"
+   echo "# No defaults found"
diff --git a/kernel/otherpatches/dongle_version.h b/kernel/otherpatches/dongle_version.h
new file mode 100644 (file)
index 0000000..8750698
--- /dev/null
@@ -0,0 +1,21 @@
+/* _______________________________________________________________________
+       dongle_version.h - Contains constants for current compatible and build
+                                               Versions
+
+       first created: 9/8/2005
+       last modified: 9/8/2005
+
+       tab size = 4
+       
+       copyright Â© 1999-2005 by Hauppauge Computer Works - all rights reserved.
+ _______________________________________________________________________*/
+
+#ifndef _dongle_version_
+#define _dongle_version_
+
+#define HCW_COMPATIBLE_VERSION 0x01010003
+#define HCW_BUILD_VERSION      0x01012C03
+
+#endif /* _dongle_version_ */
+
+/*______________________________________________________________________*/
diff --git a/kernel/otherpatches/fullduplex.patch b/kernel/otherpatches/fullduplex.patch
new file mode 100644 (file)
index 0000000..b4594f6
--- /dev/null
@@ -0,0 +1,38 @@
+diff -Narup kernel/drivers/net/smc91111.c dev/mvpdist/kernel/drivers/net/smc91111.c
+--- kernel/drivers/net/smc91111.c      2003-11-13 23:14:34.000000000 +0100
++++ kernel/drivers/net/smc91111.c      2006-11-27 02:22:29.000000000 +0100
+@@ -1400,7 +1400,7 @@ static int smc_open(struct net_device *d
+       lp->ctl_ephloop = 0;
+       lp->ctl_miiop = 0;
+       lp->ctl_autoneg = 1;    //1
+-      lp->ctl_rfduplx = 0;    //Haup=> negotiate for HALF?
++      lp->ctl_rfduplx = 1;    //1
+       lp->ctl_rspeed = 100;   //100
+       lp->ctl_afduplx = 0;    //1
+       lp->ctl_aspeed = 100;   //100
+@@ -3742,5 +3742,25 @@ static void smc_phy_interrupt(struct net
+ #endif
+               // Update the last phy 18 variable
+               lp->lastPhy18 = phy18;
++              
++              // if Fullduplex and 100MBit detected we set swfdup
++              if (lp->lastPhy18 & PHY_INT_DPLXDET &&
++                                      lp->lastPhy18 & PHY_INT_SPDDET)
++              {
++                      if (!(lp->tcr_cur_mode & TCR_SWFDUP))
++                      {
++                              PRINTK2 ("SMC91111 detect 100MBit Full Duplex.. enable swfdup\n");
++                              lp->tcr_cur_mode |= TCR_SWFDUP;
++                              lp->ctl_swfdup = 1;
++                              smc_modify_regbit (0, ioaddr, TCR_REG, TCR_SWFDUP, 1);
++                      }
++              }
++              else if (lp->tcr_cur_mode & TCR_SWFDUP)
++              {
++                      PRINTK2 ("SMC91111 no 100MBit Full Duplex detected.. disable swfdup\n");
++                      lp->tcr_cur_mode &= ~TCR_SWFDUP;
++                      lp->ctl_swfdup = 0;
++                      smc_modify_regbit (0, ioaddr, TCR_REG, TCR_SWFDUP, 0);
++              }
+       }
+ }
diff --git a/kernel/otherpatches/ppcfix.patch b/kernel/otherpatches/ppcfix.patch
new file mode 100644 (file)
index 0000000..c75bc30
--- /dev/null
@@ -0,0 +1,31 @@
+diff -Narup linux-2.4.31-orig/arch/ppc/boot/utils/mktree.c linux-2.4.31/arch/ppc/boot/utils/mktree.c
+--- linux-2.4.31-orig/arch/ppc/boot/utils/mktree.c      2004-08-03 16:31:09.568992888 -0500
++++ linux-2.4.31/arch/ppc/boot/utils/mktree.c   2004-08-04 11:06:39.799051328 -0500
+@@ -15,19 +15,20 @@
+ #include <sys/stat.h>
+ #include <unistd.h>
+ #include <netinet/in.h>
++#include <stdint.h>
+ /* This gets tacked on the front of the image.  There are also a few
+  * bytes allocated after the _start label used by the boot rom (see
+  * head.S for details).
+  */
+ typedef struct boot_block {
+-      unsigned long bb_magic;         /* 0x0052504F */
+-      unsigned long bb_dest;          /* Target address of the image */
+-      unsigned long bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */
+-      unsigned long bb_debug_flag;    /* Run debugger or image after load */
+-      unsigned long bb_entry_point;   /* The image address to start */
+-      unsigned long bb_checksum;      /* 32 bit checksum including header */
+-      unsigned long reserved[2];
++       uint32_t bb_magic;              /* 0x0052504F */
++       uint32_t bb_dest;               /* Target address of the image */
++       uint32_t bb_num_512blocks;      /* Size, rounded-up, in 512 byte blks */
++       uint32_t bb_debug_flag; /* Run debugger or image after load */
++       uint32_t bb_entry_point;        /* The image address to start */
++       uint32_t bb_checksum;   /* 32 bit checksum including header */
++       uint32_t reserved[2];
+ } boot_block_t;
+ #define IMGBLK        512
diff --git a/kernel/patch b/kernel/patch
new file mode 100755 (executable)
index 0000000..c9e9719
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+for j in $( ls patches-2.4.31/*.patch); do
+  patch -f -N -p1 -d $1/linux-2.4.31 < $j
+done
+
+for j in $( ls otherpatches/*.patch); do
+  patch -f -N -p1 -d $1/linux-2.4.31 < $j
+done
+
+cp -vf patches-2.4.31/redwood.c $1/linux-2.4.31/drivers/mtd/maps
+cp -vf otherpatches/dongle_version.h $1/linux-2.4.31/arch/ppc
diff --git a/kernel/patches-2.4.31/architecture.patch b/kernel/patches-2.4.31/architecture.patch
new file mode 100644 (file)
index 0000000..020f959
--- /dev/null
@@ -0,0 +1,24 @@
+diff -Narup linux-2.4.31-orig/Makefile linux-2.4.31/Makefile
+--- linux-2.4.31-orig/Makefile 2005-08-09 11:30:57.000000000 -0700
++++ linux-2.4.31/Makefile      2005-08-09 11:33:15.000000000 -0700
+@@ -5,7 +5,7 @@ EXTRAVERSION =
+ KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+-ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
++#ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
+ KERNELPATH=kernel-$(shell echo $(KERNELRELEASE) | sed -e "s/-//g")
+ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
+@@ -19,7 +19,10 @@ FINDHPATH   = $(HPATH)/asm $(HPATH)/linux 
+ HOSTCC        = gcc
+ HOSTCFLAGS    = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+-CROSS_COMPILE         =
++#CROSS_COMPILE        =
++
++ARCH=ppc
++CROSS_COMPILE = powerpc-405-linux-gnu-
+ #
+ # Include the make variables (CC, etc...)
diff --git a/kernel/patches-2.4.31/clockfix.patch b/kernel/patches-2.4.31/clockfix.patch
new file mode 100644 (file)
index 0000000..ae063ca
--- /dev/null
@@ -0,0 +1,13 @@
+diff -Narup linux-2.4.31-orig/arch/ppc/boot/simple/embed_config.c linux-2.4.31/arch/ppc/boot/simple/embed_config.c
+--- linux-2.4.31-orig/arch/ppc/boot/simple/embed_config.c      2004-04-14 06:05:27.000000000 -0700
++++ linux-2.4.31/arch/ppc/boot/simple/embed_config.c   2005-10-06 00:05:18.000000000 -0700
+@@ -711,6 +711,9 @@ embed_config(bd_t **bdp)
+               bd->bi_tbfreq = bd->bi_intfreq;
+ #endif
+       }
++#if defined (CONFIG_REDWOOD_5) || defined (CONFIG_REDWOOD_6)
++              bd->bi_tbfreq = 27 * 1000 * 1000;
++#endif
+ }
+ #endif
diff --git a/kernel/patches-2.4.31/kexec-ppc-2.4.patch b/kernel/patches-2.4.31/kexec-ppc-2.4.patch
new file mode 100644 (file)
index 0000000..b4f5ca2
--- /dev/null
@@ -0,0 +1,1685 @@
+diff -Narup linux-2.4.31-orig/arch/ppc/config.in linux-2.4.31/arch/ppc/config.in
+--- linux-2.4.31-orig/arch/ppc/config.in       2004-08-07 16:26:04.000000000 -0700
++++ linux-2.4.31/arch/ppc/config.in    2005-08-24 22:14:47.000000000 -0700
+@@ -167,6 +167,8 @@ if [ "$CONFIG_SMP" = "y" ]; then
+   int  'Maximum number of CPUs (2-32)' CONFIG_NR_CPUS 32
+ fi
++bool 'kexec system call' CONFIG_KEXEC
++
+ if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then
+   bool 'AltiVec Support' CONFIG_ALTIVEC
+   bool 'Thermal Management Support' CONFIG_TAU
+diff -Narup linux-2.4.31-orig/arch/ppc/kernel/Makefile linux-2.4.31/arch/ppc/kernel/Makefile
+--- linux-2.4.31-orig/arch/ppc/kernel/Makefile 2004-04-14 06:05:27.000000000 -0700
++++ linux-2.4.31/arch/ppc/kernel/Makefile      2005-08-24 22:17:32.000000000 -0700
+@@ -49,6 +49,7 @@ obj-$(CONFIG_PCI)            += pci-dma.o
+ obj-$(CONFIG_KGDB)            += ppc-stub.o
+ obj-$(CONFIG_PPCBUG_NVRAM)    += prep_nvram.o
+ obj-$(CONFIG_SMP)             += smp.o
++obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
+ obj-$(CONFIG_TAU)             += temp.o
+ ifeq ($(CONFIG_SERIAL)$(CONFIG_GEN550),yy)
+ obj-$(CONFIG_KGDB)            += gen550_kgdb.o gen550_dbg.o
+diff -Narup linux-2.4.31-orig/arch/ppc/kernel/machine_kexec.c linux-2.4.31/arch/ppc/kernel/machine_kexec.c
+--- linux-2.4.31-orig/arch/ppc/kernel/machine_kexec.c  1969-12-31 16:00:00.000000000 -0800
++++ linux-2.4.31/arch/ppc/kernel/machine_kexec.c       2005-08-24 23:43:17.000000000 -0700
+@@ -0,0 +1,121 @@
++/*
++ * machine_kexec.c - handle transition of Linux booting another kernel
++ * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
++ *
++ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
++ *
++ * This source code is licensed under the GNU General Public License,
++ * Version 2.  See the file COPYING for more details.
++ */
++
++#include <linux/mm.h>
++#include <linux/kexec.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++#include <asm/mmu_context.h>
++#include <asm/io.h>
++#include <asm/hw_irq.h>
++//#include <asm/cacheflush.h>
++#include <asm/machdep.h>
++
++typedef NORET_TYPE void (*relocate_new_kernel_t)(
++      unsigned long indirection_page, unsigned long reboot_code_buffer,
++      unsigned long start_address) ATTRIB_NORET;
++
++const extern unsigned char relocate_new_kernel[];
++const extern unsigned int relocate_new_kernel_size;
++
++void machine_shutdown(void)
++{
++      if (ppc_md.machine_shutdown) {
++              ppc_md.machine_shutdown();
++      }
++}
++
++void machine_crash_shutdown(void)
++{
++      if (ppc_md.machine_crash_shutdown) {
++              ppc_md.machine_crash_shutdown();
++      }
++}
++
++/*
++ * Do what every setup is needed on image and the
++ * reboot code buffer to allow us to avoid allocations
++ * later.
++ */
++int machine_kexec_prepare(struct kimage *image)
++{
++      if (ppc_md.machine_kexec_prepare) {
++              return ppc_md.machine_kexec_prepare(image);
++      }
++      /*
++       * Fail if platform doesn't provide its own machine_kexec_prepare
++       * implementation.
++       */
++      return -ENOSYS;
++}
++
++void machine_kexec_cleanup(struct kimage *image)
++{
++      if (ppc_md.machine_kexec_cleanup) {
++              ppc_md.machine_kexec_cleanup(image);
++      }
++}
++
++/*
++ * Do not allocate memory (or fail in any way) in machine_kexec().
++ * We are past the point of no return, committed to rebooting now.
++ */
++NORET_TYPE void machine_kexec(struct kimage *image)
++{
++      if (ppc_md.machine_kexec) {
++              ppc_md.machine_kexec(image);
++      } else {
++              /*
++               * Fall back to normal restart if platform doesn't provide
++               * its own kexec function, and user insist to kexec...
++               */
++              machine_restart(NULL);
++      }
++      for(;;);
++}
++
++
++/*
++ * This is a generic machine_kexec function suitable at least for
++ * non-OpenFirmware embedded platforms.
++ * It merely copies the image relocation code to the control page and
++ * jumps to it.
++ * A platform specific function may just call this one.
++ */
++void machine_kexec_simple(struct kimage *image)
++{
++      unsigned long page_list;
++      unsigned long reboot_code_buffer, reboot_code_buffer_phys;
++      relocate_new_kernel_t rnk;
++
++      /* Interrupts aren't acceptable while we reboot */
++      local_irq_disable();
++
++      page_list = image->head;
++
++      /* we need both effective and real address here */
++      reboot_code_buffer =
++              (unsigned long)page_address(image->control_code_page);
++      reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
++
++      /* copy our kernel relocation code to the control code page */
++      memcpy((void *)reboot_code_buffer,
++              relocate_new_kernel, relocate_new_kernel_size);
++
++      flush_icache_range(reboot_code_buffer,
++              reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
++      printk(KERN_INFO "Bye!\n");
++
++      /* now call it */
++      rnk = (relocate_new_kernel_t) reboot_code_buffer;
++      (*rnk)(page_list, reboot_code_buffer_phys, image->start);
++}
+diff -Narup linux-2.4.31-orig/arch/ppc/kernel/misc.S linux-2.4.31/arch/ppc/kernel/misc.S
+--- linux-2.4.31-orig/arch/ppc/kernel/misc.S   2004-04-14 06:05:27.000000000 -0700
++++ linux-2.4.31/arch/ppc/kernel/misc.S        2005-08-24 22:22:21.000000000 -0700
+@@ -1310,6 +1310,25 @@ _GLOBAL(sys_call_table)
+       .long sys_ni_syscall    /*      reserved for sys_clock_getres */
+       .long sys_ni_syscall    /*      reserved for sys_clock_nanosleep */
+       .long sys_swapcontext
++      .long sys_ni_syscall    /* 250 */
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall    /* 255 */
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall    /* 260 */
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_ni_syscall    /* 265 */
++      .long sys_ni_syscall
++      .long sys_ni_syscall
++      .long sys_kexec_load    /* and finally, 268 sys_kexec_load... */
+       .rept NR_syscalls-(.-sys_call_table)/4
+               .long sys_ni_syscall
+diff -Narup linux-2.4.31-orig/arch/ppc/kernel/relocate_kernel.S linux-2.4.31/arch/ppc/kernel/relocate_kernel.S
+--- linux-2.4.31-orig/arch/ppc/kernel/relocate_kernel.S        1969-12-31 16:00:00.000000000 -0800
++++ linux-2.4.31/arch/ppc/kernel/relocate_kernel.S     2005-08-24 11:37:15.000000000 -0700
+@@ -0,0 +1,122 @@
++/*
++ * relocate_kernel.S - put the kernel image in place to boot
++ * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
++ *
++ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
++ *
++ * This source code is licensed under the GNU General Public License,
++ * Version 2.  See the file COPYING for more details.
++ */
++
++#include <asm/ppc_asm.h>
++#include <asm/processor.h>
++
++#include <asm/kexec.h>
++
++#define PAGE_SIZE      4096 /* must be same value as in <asm/page.h> */
++
++      /*
++       * Must be relocatable PIC code callable as a C function.
++       */
++      .globl relocate_new_kernel
++relocate_new_kernel:
++      /* r3 = page_list   */
++      /* r4 = reboot_code_buffer */
++      /* r5 = start_address      */
++
++      li      r0, 0
++
++      /*
++       * Set Machine Status Register to a known status,
++       * switch the MMU off and jump to 1: in a single step.
++       */
++
++      mr      r8, r0
++      ori     r8, r8, MSR_RI|MSR_ME
++      mtspr   SPRN_SRR1, r8
++      addi    r8, r4, 1f - relocate_new_kernel
++      mtspr   SPRN_SRR0, r8
++      sync
++      rfi
++
++1:
++      /* from this point address translation is turned off */
++      /* and interrupts are disabled */
++
++      /* set a new stack at the bottom of our page... */
++      /* (not really needed now) */
++      addi    r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
++      stw     r0, 0(r1)
++
++      /* Do the copies */
++      li      r6, 0 /* checksum */
++      mr      r0, r3
++      b       1f
++
++0:    /* top, read another word for the indirection page */
++      lwzu    r0, 4(r3)
++
++1:
++      /* is it a destination page? (r8) */
++      rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
++      beq     2f
++
++      rlwinm  r8, r0, 0, 0, 19 /* clear kexec flags, page align */
++      b       0b
++
++2:    /* is it an indirection page? (r3) */
++      rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
++      beq     2f
++
++      rlwinm  r3, r0, 0, 0, 19 /* clear kexec flags, page align */
++      subi    r3, r3, 4
++      b       0b
++
++2:    /* are we done? */
++      rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
++      beq     2f
++      b       3f
++
++2:    /* is it a source page? (r9) */
++      rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
++      beq     0b
++
++      rlwinm  r9, r0, 0, 0, 19 /* clear kexec flags, page align */
++
++      li      r7, PAGE_SIZE / 4
++      mtctr   r7
++      subi    r9, r9, 4
++      subi    r8, r8, 4
++9:
++      lwzu    r0, 4(r9)  /* do the copy */
++      xor     r6, r6, r0
++      stwu    r0, 4(r8)
++      dcbst   0, r8
++      sync
++      icbi    0, r8
++      bdnz    9b
++
++      addi    r9, r9, 4
++      addi    r8, r8, 4
++      b       0b
++
++3:
++
++      /* To be certain of avoiding problems with self-modifying code
++       * execute a serializing instruction here.
++       */
++      isync
++      sync
++
++      /* jump to the entry point, usually the setup routine */
++      mtlr    r5
++      blrl
++
++1:    b       1b
++
++relocate_new_kernel_end:
++
++      .globl relocate_new_kernel_size
++relocate_new_kernel_size:
++      .long relocate_new_kernel_end - relocate_new_kernel
++
+diff -Narup linux-2.4.31-orig/arch/ppc/platforms/redwood6.c linux-2.4.31/arch/ppc/platforms/redwood6.c
+--- linux-2.4.31-orig/arch/ppc/platforms/redwood6.c    2004-04-14 06:05:27.000000000 -0700
++++ linux-2.4.31/arch/ppc/platforms/redwood6.c 2005-08-24 22:57:12.000000000 -0700
+@@ -168,7 +168,26 @@ board_setup_irq(void)
+ {
+ }
++#ifdef CONFIG_KEXEC
++int redwood6_kexec_prepare(struct kimage *image)
++{
++      /* here, we can place additional preparations */
++      return 0; /* yes, we support kexec */
++}
++                                                      
++                         
++void redwood6_kexec(struct kimage *image)
++{
++      /* just call the simple kexec version... */
++      machine_kexec_simple(image);
++}
++#endif /* CONFIG_KEXEC */
++
+ void __init
+ board_init(void)
+ {
++#ifdef CONFIG_KEXEC
++      ppc_md.machine_kexec_prepare = redwood6_kexec_prepare;
++      ppc_md.machine_kexec = redwood6_kexec;
++#endif
+ }
+diff -Narup linux-2.4.31-orig/include/asm-ppc/io.h linux-2.4.31/include/asm-ppc/io.h
+--- linux-2.4.31-orig/include/asm-ppc/io.h     2003-11-28 10:26:21.000000000 -0800
++++ linux-2.4.31/include/asm-ppc/io.h  2005-08-24 23:28:30.000000000 -0700
+@@ -275,6 +275,10 @@ extern inline void * phys_to_virt(unsign
+ #define page_to_phys(page)    (((page - mem_map) << PAGE_SHIFT) + PPC_MEMSTART)
+ #define page_to_bus(page)     (page_to_phys(page) + PCI_DRAM_OFFSET)
++/* added for kexec support */
++#define pfn_to_page(pfn)      (mem_map + ((pfn) - PPC_PGSTART))
++#define page_to_pfn(page)     ((unsigned long)((page) - mem_map) + PPC_PGSTART)
++
+ /*
+  * Enforce In-order Execution of I/O:
+  * Acts as a barrier to ensure all previous I/O accesses have
+diff -Narup linux-2.4.31-orig/include/asm-ppc/kexec.h linux-2.4.31/include/asm-ppc/kexec.h
+--- linux-2.4.31-orig/include/asm-ppc/kexec.h  1969-12-31 16:00:00.000000000 -0800
++++ linux-2.4.31/include/asm-ppc/kexec.h       2005-08-24 22:58:28.000000000 -0700
+@@ -0,0 +1,38 @@
++#ifndef _PPC_KEXEC_H
++#define _PPC_KEXEC_H
++
++#ifdef CONFIG_KEXEC
++
++/*
++ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
++ * I.e. Maximum page that is mapped directly into kernel memory,
++ * and kmap is not required.
++ *
++ * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
++ * calculation for the amount of memory directly mappable into the
++ * kernel memory space.
++ */
++
++/* Maximum physical address we can use pages from */
++#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
++/* Maximum address we can reach in physical address mode */
++#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
++/* Maximum address we can use for the control code buffer */
++#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
++
++#define KEXEC_CONTROL_CODE_SIZE       4096
++
++/* The native architecture */
++#define KEXEC_ARCH KEXEC_ARCH_PPC
++
++#ifndef __ASSEMBLY__
++
++struct kimage;
++
++extern void machine_kexec_simple(struct kimage *image);
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* CONFIG_KEXEC */
++
++#endif /* _PPC_KEXEC_H */
+diff -Narup linux-2.4.31-orig/include/asm-ppc/machdep.h linux-2.4.31/include/asm-ppc/machdep.h
+--- linux-2.4.31-orig/include/asm-ppc/machdep.h        2005-08-24 22:05:10.000000000 -0700
++++ linux-2.4.31/include/asm-ppc/machdep.h     2005-08-24 23:41:01.000000000 -0700
+@@ -3,6 +3,7 @@
+ #define _PPC_MACHDEP_H
+ #include <linux/config.h>
++#include <linux/kexec.h>
+ #ifdef CONFIG_APUS
+ #include <asm-m68k/machdep.h>
+@@ -113,6 +114,36 @@ struct machdep_calls {
+       /* functions for dealing with other cpus */
+       struct smp_ops_t *smp_ops;
+ #endif /* CONFIG_SMP */
++
++#ifdef CONFIG_KEXEC
++      /* Called to shutdown machine specific hardware not already controlled
++       * by other drivers.
++       * XXX Should we move this one out of kexec scope?
++       */
++      void (*machine_shutdown)(void);
++
++      /* Called to do the minimal shutdown needed to run a kexec'd kernel
++       * to run successfully.
++       * XXX Should we move this one out of kexec scope?
++       */
++      void (*machine_crash_shutdown)(void);
++
++      /* Called to do what every setup is needed on image and the
++       * reboot code buffer. Returns 0 on success.
++       * Provide your own (maybe dummy) implementation if your platform
++       * claims to support kexec.
++       */
++      int (*machine_kexec_prepare)(struct kimage *image);
++
++      /* Called to handle any machine specific cleanup on image */
++      void (*machine_kexec_cleanup)(struct kimage *image);
++
++      /* Called to perform the _real_ kexec.
++       * Do NOT allocate memory or fail here. We are past the point of
++       * no return.
++       */
++      void (*machine_kexec)(struct kimage *image);
++#endif /* CONFIG_KEXEC */
+ };
+ extern struct machdep_calls ppc_md;
+diff -Narup linux-2.4.31-orig/include/asm-ppc/page.h linux-2.4.31/include/asm-ppc/page.h
+--- linux-2.4.31-orig/include/asm-ppc/page.h   2003-11-28 10:26:21.000000000 -0800
++++ linux-2.4.31/include/asm-ppc/page.h        2005-08-24 23:27:19.000000000 -0700
+@@ -104,6 +104,7 @@ extern unsigned long ppc_memstart;
+ extern unsigned long ppc_memoffset;
+ #ifndef CONFIG_APUS
+ #define PPC_MEMSTART  0
++#define PPC_PGSTART           0
+ #define PPC_MEMOFFSET PAGE_OFFSET
+ #else
+ #define PPC_MEMSTART  ppc_memstart
+diff -Narup linux-2.4.31-orig/include/asm-ppc/unistd.h linux-2.4.31/include/asm-ppc/unistd.h
+--- linux-2.4.31-orig/include/asm-ppc/unistd.h 2004-11-17 03:54:22.000000000 -0800
++++ linux-2.4.31/include/asm-ppc/unistd.h      2005-08-24 22:49:47.000000000 -0700
+@@ -257,6 +257,8 @@
+ #endif
+ #define __NR_swapcontext      249
++#define __NR_kexec_load               268
++
+ #define __NR(n)       #n
+ /* On powerpc a system call basically clobbers the same registers like a
+diff -Narup linux-2.4.31-orig/include/linux/kexec.h linux-2.4.31/include/linux/kexec.h
+--- linux-2.4.31-orig/include/linux/kexec.h    1969-12-31 16:00:00.000000000 -0800
++++ linux-2.4.31/include/linux/kexec.h 2005-08-24 23:40:30.000000000 -0700
+@@ -0,0 +1,115 @@
++#ifndef LINUX_KEXEC_H
++#define LINUX_KEXEC_H
++
++#ifdef CONFIG_KEXEC
++#include <linux/compiler.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/list.h>
++#include <linux/linkage.h>
++#include <asm/kexec.h>
++
++/* Verify architecture specific macros are defined */
++
++#ifndef KEXEC_SOURCE_MEMORY_LIMIT
++#error KEXEC_SOURCE_MEMORY_LIMIT not defined
++#endif
++
++#ifndef KEXEC_DESTINATION_MEMORY_LIMIT
++#error KEXEC_DESTINATION_MEMORY_LIMIT not defined
++#endif
++
++#ifndef KEXEC_CONTROL_MEMORY_LIMIT
++#error KEXEC_CONTROL_MEMORY_LIMIT not defined
++#endif
++
++#ifndef KEXEC_CONTROL_CODE_SIZE
++#error KEXEC_CONTROL_CODE_SIZE not defined
++#endif
++
++#ifndef KEXEC_ARCH
++#error KEXEC_ARCH not defined
++#endif
++
++/*
++ * This structure is used to hold the arguments that are used when loading
++ * kernel binaries.
++ */
++
++typedef unsigned long kimage_entry_t;
++#define IND_DESTINATION  0x1
++#define IND_INDIRECTION  0x2
++#define IND_DONE         0x4
++#define IND_SOURCE       0x8
++
++#define KEXEC_SEGMENT_MAX 8
++struct kexec_segment {
++      void __user *buf;
++      size_t bufsz;
++      unsigned long mem;      /* User space sees this as a (void *) ... */
++      size_t memsz;
++};
++
++struct kimage {
++      kimage_entry_t head;
++      kimage_entry_t *entry;
++      kimage_entry_t *last_entry;
++
++      unsigned long destination;
++
++      unsigned long start;
++      struct page *control_code_page;
++
++      unsigned long nr_segments;
++      struct kexec_segment segment[KEXEC_SEGMENT_MAX];
++
++      struct list_head control_pages;
++      struct list_head dest_pages;
++      struct list_head unuseable_pages;
++
++      /* Address of next control page to allocate for crash kernels. */
++      unsigned long control_page;
++
++      /* Flags to indicate special processing */
++      unsigned int type : 1;
++#define KEXEC_TYPE_DEFAULT 0
++#define KEXEC_TYPE_CRASH   1
++};
++
++
++
++/* kexec interface functions */
++extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET;
++extern int machine_kexec_prepare(struct kimage *image);
++extern void machine_kexec_cleanup(struct kimage *image);
++extern asmlinkage long sys_kexec_load(unsigned long entry,
++      unsigned long nr_segments, struct kexec_segment __user *segments,
++      unsigned long flags);
++extern struct page *kimage_alloc_control_pages(struct kimage *image, unsigned int order);
++extern void crash_kexec(void);
++extern struct kimage *kexec_image;
++extern struct kimage *kexec_crash_image;
++
++#define KEXEC_ON_CRASH  0x00000001
++#define KEXEC_ARCH_MASK 0xffff0000
++
++/* These values match the ELF architecture values.
++ * Unless there is a good reason that should continue to be the case.
++ */
++#define KEXEC_ARCH_DEFAULT ( 0 << 16)
++#define KEXEC_ARCH_386     ( 3 << 16)
++#define KEXEC_ARCH_X86_64  (62 << 16)
++#define KEXEC_ARCH_PPC     (20 << 16)
++#define KEXEC_ARCH_PPC64   (21 << 16)
++#define KEXEC_ARCH_IA_64   (50 << 16)
++
++#define KEXEC_FLAGS    (KEXEC_ON_CRASH)  /* List of defined/legal kexec flags */
++
++/* Location of a reserved region to hold the crash kernel.
++ */
++extern struct resource crashk_res;
++
++#else /* !CONFIG_KEXEC */
++static inline void crash_kexec(void) { }
++#endif /* CONFIG_KEXEC */
++#endif /* LINUX_KEXEC_H */
+diff -Narup linux-2.4.31-orig/include/linux/mm.h linux-2.4.31/include/linux/mm.h
+--- linux-2.4.31-orig/include/linux/mm.h       2005-01-19 06:10:12.000000000 -0800
++++ linux-2.4.31/include/linux/mm.h    2005-08-24 23:27:57.000000000 -0700
+@@ -165,6 +165,8 @@ typedef struct page {
+       struct page **pprev_hash;       /* Complement to *next_hash. */
+       struct buffer_head * buffers;   /* Buffer maps us to a disk block. */
++      unsigned long private; /* added for kexec */
++      
+       /*
+        * On machines where all RAM is mapped into kernel address space,
+        * we can simply calculate the virtual address. On machines with
+diff -Narup linux-2.4.31-orig/include/linux/reboot.h linux-2.4.31/include/linux/reboot.h
+--- linux-2.4.31-orig/include/linux/reboot.h   2001-02-09 14:46:13.000000000 -0800
++++ linux-2.4.31/include/linux/reboot.h        2005-08-24 23:00:54.000000000 -0700
+@@ -20,6 +20,7 @@
+  * CAD_OFF     Ctrl-Alt-Del sequence sends SIGINT to init task.
+  * POWER_OFF   Stop OS and remove all power from system, if possible.
+  * RESTART2    Restart system using given command string.
++ * KEXEC       Restart system using a previously loaded Linux kernel
+  */
+ #define       LINUX_REBOOT_CMD_RESTART        0x01234567
+@@ -28,6 +29,7 @@
+ #define       LINUX_REBOOT_CMD_CAD_OFF        0x00000000
+ #define       LINUX_REBOOT_CMD_POWER_OFF      0x4321FEDC
+ #define       LINUX_REBOOT_CMD_RESTART2       0xA1B2C3D4
++#define       LINUX_REBOOT_CMD_KEXEC          0x45584543
+ #ifdef __KERNEL__
+@@ -45,6 +47,8 @@ extern int unregister_reboot_notifier(st
+ extern void machine_restart(char *cmd);
+ extern void machine_halt(void);
+ extern void machine_power_off(void);
++extern void machine_shutdown(void);
++extern void machine_crash_shutdown(void);
+ #endif
+diff -Narup linux-2.4.31-orig/kernel/Makefile linux-2.4.31/kernel/Makefile
+--- linux-2.4.31-orig/kernel/Makefile  2001-09-16 21:22:40.000000000 -0700
++++ linux-2.4.31/kernel/Makefile       2005-08-24 22:38:41.000000000 -0700
+@@ -19,6 +19,7 @@ obj-y     = sched.o dma.o fork.o exec_do
+ obj-$(CONFIG_UID16) += uid16.o
+ obj-$(CONFIG_MODULES) += ksyms.o
+ obj-$(CONFIG_PM) += pm.o
++obj-$(CONFIG_KEXEC) += kexec.o
+ ifneq ($(CONFIG_IA64),y)
+ # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
+diff -Narup linux-2.4.31-orig/kernel/kexec.c linux-2.4.31/kernel/kexec.c
+--- linux-2.4.31-orig/kernel/kexec.c   1969-12-31 16:00:00.000000000 -0800
++++ linux-2.4.31/kernel/kexec.c        2005-08-24 23:30:47.000000000 -0700
+@@ -0,0 +1,993 @@
++/*
++ * kexec.c - kexec system call
++ * Copyright (C) 2002-2004 Eric Biederman  <ebiederm@xmission.com>
++ *
++ * This source code is licensed under the GNU General Public License,
++ * Version 2.  See the file COPYING for more details.
++ */
++
++#include <linux/mm.h>
++#include <linux/file.h>
++#include <linux/slab.h>
++#include <linux/fs.h>
++#include <linux/kexec.h>
++#include <linux/spinlock.h>
++#include <linux/list.h>
++#include <linux/highmem.h>
++#include <linux/reboot.h>
++//#include <linux/syscalls.h>
++#include <linux/ioport.h>
++#include <asm/page.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <asm/semaphore.h>
++
++/* Location of the reserved area for the crash kernel */
++struct resource crashk_res = {
++      .name  = "Crash kernel",
++      .start = 0,
++      .end   = 0,
++      .flags = IORESOURCE_BUSY | IORESOURCE_MEM
++};
++
++/*
++ * When kexec transitions to the new kernel there is a one-to-one
++ * mapping between physical and virtual addresses.  On processors
++ * where you can disable the MMU this is trivial, and easy.  For
++ * others it is still a simple predictable page table to setup.
++ *
++ * In that environment kexec copies the new kernel to its final
++ * resting place.  This means I can only support memory whose
++ * physical address can fit in an unsigned long.  In particular
++ * addresses where (pfn << PAGE_SHIFT) > ULONG_MAX cannot be handled.
++ * If the assembly stub has more restrictive requirements
++ * KEXEC_SOURCE_MEMORY_LIMIT and KEXEC_DEST_MEMORY_LIMIT can be
++ * defined more restrictively in <asm/kexec.h>.
++ *
++ * The code for the transition from the current kernel to the
++ * the new kernel is placed in the control_code_buffer, whose size
++ * is given by KEXEC_CONTROL_CODE_SIZE.  In the best case only a single
++ * page of memory is necessary, but some architectures require more.
++ * Because this memory must be identity mapped in the transition from
++ * virtual to physical addresses it must live in the range
++ * 0 - TASK_SIZE, as only the user space mappings are arbitrarily
++ * modifiable.
++ *
++ * The assembly stub in the control code buffer is passed a linked list
++ * of descriptor pages detailing the source pages of the new kernel,
++ * and the destination addresses of those source pages.  As this data
++ * structure is not used in the context of the current OS, it must
++ * be self-contained.
++ *
++ * The code has been made to work with highmem pages and will use a
++ * destination page in its final resting place (if it happens
++ * to allocate it).  The end product of this is that most of the
++ * physical address space, and most of RAM can be used.
++ *
++ * Future directions include:
++ *  - allocating a page table with the control code buffer identity
++ *    mapped, to simplify machine_kexec and make kexec_on_panic more
++ *    reliable.
++ */
++
++/*
++ * KIMAGE_NO_DEST is an impossible destination address..., for
++ * allocating pages whose destination address we do not care about.
++ */
++#define KIMAGE_NO_DEST (-1UL)
++
++static int kimage_is_destination_range(
++      struct kimage *image, unsigned long start, unsigned long end);
++static struct page *kimage_alloc_page(struct kimage *image, unsigned int gfp_mask, unsigned long dest);
++
++static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
++      unsigned long nr_segments, struct kexec_segment __user *segments)
++{
++      size_t segment_bytes;
++      struct kimage *image;
++      unsigned long i;
++      int result;
++
++      /* Allocate a controlling structure */
++      result = -ENOMEM;
++      image = kmalloc(sizeof(*image), GFP_KERNEL);
++      if (!image) {
++              goto out;
++      }
++      memset(image, 0, sizeof(*image));
++      image->head = 0;
++      image->entry = &image->head;
++      image->last_entry = &image->head;
++      image->control_page = ~0; /* By default this does not apply */
++      image->start = entry;
++      image->type = KEXEC_TYPE_DEFAULT;
++
++      /* Initialize the list of control pages */
++      INIT_LIST_HEAD(&image->control_pages);
++
++      /* Initialize the list of destination pages */
++      INIT_LIST_HEAD(&image->dest_pages);
++
++      /* Initialize the list of unuseable pages */
++      INIT_LIST_HEAD(&image->unuseable_pages);
++
++      /* Read in the segments */
++      image->nr_segments = nr_segments;
++      segment_bytes = nr_segments * sizeof(*segments);
++      result = copy_from_user(image->segment, segments, segment_bytes);
++      if (result)
++              goto out;
++
++      /*
++       * Verify we have good destination addresses.  The caller is
++       * responsible for making certain we don't attempt to load
++       * the new image into invalid or reserved areas of RAM.  This
++       * just verifies it is an address we can use.
++       *
++       * Since the kernel does everything in page size chunks ensure
++       * the destination addreses are page aligned.  Too many
++       * special cases crop of when we don't do this.  The most
++       * insidious is getting overlapping destination addresses
++       * simply because addresses are changed to page size
++       * granularity.
++       */
++      result = -EADDRNOTAVAIL;
++      for (i = 0; i < nr_segments; i++) {
++              unsigned long mstart, mend;
++              mstart = image->segment[i].mem;
++              mend   = mstart + image->segment[i].memsz;
++              if ((mstart & ~PAGE_MASK) || (mend & ~PAGE_MASK))
++                      goto out;
++              if (mend >= KEXEC_DESTINATION_MEMORY_LIMIT)
++                      goto out;
++      }
++
++      /* Verify our destination addresses do not overlap.
++       * If we alloed overlapping destination addresses
++       * through very weird things can happen with no
++       * easy explanation as one segment stops on another.
++       */
++      result = -EINVAL;
++      for(i = 0; i < nr_segments; i++) {
++              unsigned long mstart, mend;
++              unsigned long j;
++              mstart = image->segment[i].mem;
++              mend   = mstart + image->segment[i].memsz;
++              for(j = 0; j < i; j++) {
++                      unsigned long pstart, pend;
++                      pstart = image->segment[j].mem;
++                      pend   = pstart + image->segment[j].memsz;
++                      /* Do the segments overlap ? */
++                      if ((mend > pstart) && (mstart < pend))
++                              goto out;
++              }
++      }
++
++      /* Ensure our buffer sizes are strictly less than
++       * our memory sizes.  This should always be the case,
++       * and it is easier to check up front than to be surprised
++       * later on.
++       */
++      result = -EINVAL;
++      for(i = 0; i < nr_segments; i++) {
++              if (image->segment[i].bufsz > image->segment[i].memsz)
++                      goto out;
++      }
++
++
++      result = 0;
++ out:
++      if (result == 0) {
++              *rimage = image;
++      } else {
++              kfree(image);
++      }
++      return result;
++
++}
++
++static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
++      unsigned long nr_segments, struct kexec_segment __user *segments)
++{
++      int result;
++      struct kimage *image;
++
++      /* Allocate and initialize a controlling structure */
++      image = NULL;
++      result = do_kimage_alloc(&image, entry, nr_segments, segments);
++      if (result) {
++              goto out;
++      }
++      *rimage = image;
++
++      /*
++       * Find a location for the control code buffer, and add it
++       * the vector of segments so that it's pages will also be
++       * counted as destination pages.
++       */
++      result = -ENOMEM;
++      image->control_code_page = kimage_alloc_control_pages(image,
++              get_order(KEXEC_CONTROL_CODE_SIZE));
++      if (!image->control_code_page) {
++              printk(KERN_ERR "Could not allocate control_code_buffer\n");
++              goto out;
++      }
++
++      result = 0;
++ out:
++      if (result == 0) {
++              *rimage = image;
++      } else {
++              kfree(image);
++      }
++      return result;
++}
++
++static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry,
++      unsigned long nr_segments, struct kexec_segment *segments)
++{
++      int result;
++      struct kimage *image;
++      unsigned long i;
++
++      image = NULL;
++      /* Verify we have a valid entry point */
++      if ((entry < crashk_res.start) || (entry > crashk_res.end)) {
++              result = -EADDRNOTAVAIL;
++              goto out;
++      }
++
++      /* Allocate and initialize a controlling structure */
++      result = do_kimage_alloc(&image, entry, nr_segments, segments);
++      if (result) {
++              goto out;
++      }
++
++      /* Enable the special crash kernel control page
++       * allocation policy.
++       */
++      image->control_page = crashk_res.start;
++      image->type = KEXEC_TYPE_CRASH;
++
++      /*
++       * Verify we have good destination addresses.  Normally
++       * the caller is responsible for making certain we don't
++       * attempt to load the new image into invalid or reserved
++       * areas of RAM.  But crash kernels are preloaded into a
++       * reserved area of ram.  We must ensure the addresses
++       * are in the reserved area otherwise preloading the
++       * kernel could corrupt things.
++       */
++      result = -EADDRNOTAVAIL;
++      for (i = 0; i < nr_segments; i++) {
++              unsigned long mstart, mend;
++              mstart = image->segment[i].mem;
++              mend = mstart + image->segment[i].memsz;
++              /* Ensure we are within the crash kernel limits */
++              if ((mstart < crashk_res.start) || (mend > crashk_res.end))
++                      goto out;
++      }
++
++
++      /*
++       * Find a location for the control code buffer, and add
++       * the vector of segments so that it's pages will also be
++       * counted as destination pages.
++       */
++      result = -ENOMEM;
++      image->control_code_page = kimage_alloc_control_pages(image,
++              get_order(KEXEC_CONTROL_CODE_SIZE));
++      if (!image->control_code_page) {
++              printk(KERN_ERR "Could not allocate control_code_buffer\n");
++              goto out;
++      }
++
++      result = 0;
++ out:
++      if (result == 0) {
++              *rimage = image;
++      } else {
++              kfree(image);
++      }
++      return result;
++}
++
++static int kimage_is_destination_range(
++      struct kimage *image, unsigned long start, unsigned long end)
++{
++      unsigned long i;
++
++      for (i = 0; i < image->nr_segments; i++) {
++              unsigned long mstart, mend;
++              mstart = image->segment[i].mem;
++              mend   = mstart + image->segment[i].memsz;
++              if ((end > mstart) && (start < mend)) {
++                      return 1;
++              }
++      }
++      return 0;
++}
++
++static struct page *kimage_alloc_pages(unsigned int gfp_mask, unsigned int order)
++{
++      struct page *pages;
++      pages = alloc_pages(gfp_mask, order);
++      if (pages) {
++              unsigned int count, i;
++              pages->mapping = NULL;
++              pages->private = order;
++              count = 1 << order;
++              for(i = 0; i < count; i++) {
++                      SetPageReserved(pages + i);
++              }
++      }
++      return pages;
++}
++
++static void kimage_free_pages(struct page *page)
++{
++      unsigned int order, count, i;
++      order = page->private;
++      count = 1 << order;
++      for(i = 0; i < count; i++) {
++              ClearPageReserved(page + i);
++      }
++      __free_pages(page, order);
++}
++
++static void kimage_free_page_list(struct list_head *list)
++{
++      struct list_head *pos, *next;
++      list_for_each_safe(pos, next, list) {
++              struct page *page;
++
++              page = list_entry(pos, struct page, lru);
++              list_del(&page->lru);
++
++              kimage_free_pages(page);
++      }
++}
++
++static struct page *kimage_alloc_normal_control_pages(
++      struct kimage *image, unsigned int order)
++{
++      /* Control pages are special, they are the intermediaries
++       * that are needed while we copy the rest of the pages
++       * to their final resting place.  As such they must
++       * not conflict with either the destination addresses
++       * or memory the kernel is already using.
++       *
++       * The only case where we really need more than one of
++       * these are for architectures where we cannot disable
++       * the MMU and must instead generate an identity mapped
++       * page table for all of the memory.
++       *
++       * At worst this runs in O(N) of the image size.
++       */
++      struct list_head extra_pages;
++      struct page *pages;
++      unsigned int count;
++
++      count = 1 << order;
++      INIT_LIST_HEAD(&extra_pages);
++
++      /* Loop while I can allocate a page and the page allocated
++       * is a destination page.
++       */
++      do {
++              unsigned long pfn, epfn, addr, eaddr;
++              pages = kimage_alloc_pages(GFP_KERNEL, order);
++              if (!pages)
++                      break;
++              pfn   = page_to_pfn(pages);
++              epfn  = pfn + count;
++              addr  = pfn << PAGE_SHIFT;
++              eaddr = epfn << PAGE_SHIFT;
++              if ((epfn >= (KEXEC_CONTROL_MEMORY_LIMIT >> PAGE_SHIFT)) ||
++                      kimage_is_destination_range(image, addr, eaddr))
++              {
++                      list_add(&pages->lru, &extra_pages);
++                      pages = NULL;
++              }
++      } while(!pages);
++      if (pages) {
++              /* Remember the allocated page... */
++              list_add(&pages->lru, &image->control_pages);
++
++              /* Because the page is already in it's destination
++               * location we will never allocate another page at
++               * that address.  Therefore kimage_alloc_pages
++               * will not return it (again) and we don't need
++               * to give it an entry in image->segment[].
++               */
++      }
++      /* Deal with the destination pages I have inadvertently allocated.
++       *
++       * Ideally I would convert multi-page allocations into single
++       * page allocations, and add everyting to image->dest_pages.
++       *
++       * For now it is simpler to just free the pages.
++       */
++      kimage_free_page_list(&extra_pages);
++      return pages;
++
++}
++
++static struct page *kimage_alloc_crash_control_pages(
++      struct kimage *image, unsigned int order)
++{
++      /* Control pages are special, they are the intermediaries
++       * that are needed while we copy the rest of the pages
++       * to their final resting place.  As such they must
++       * not conflict with either the destination addresses
++       * or memory the kernel is already using.
++       *
++       * Control pages are also the only pags we must allocate
++       * when loading a crash kernel.  All of the other pages
++       * are specified by the segments and we just memcpy
++       * into them directly.
++       *
++       * The only case where we really need more than one of
++       * these are for architectures where we cannot disable
++       * the MMU and must instead generate an identity mapped
++       * page table for all of the memory.
++       *
++       * Given the low demand this implements a very simple
++       * allocator that finds the first hole of the appropriate
++       * size in the reserved memory region, and allocates all
++       * of the memory up to and including the hole.
++       */
++      unsigned long hole_start, hole_end, size;
++      struct page *pages;
++      pages = NULL;
++      size = (1 << order) << PAGE_SHIFT;
++      hole_start = (image->control_page + (size - 1)) & ~(size - 1);
++      hole_end   = hole_start + size - 1;
++      while(hole_end <= crashk_res.end) {
++              unsigned long i;
++              if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT) {
++                      break;
++              }
++              if (hole_end > crashk_res.end) {
++                      break;
++              }
++              /* See if I overlap any of the segments */
++              for(i = 0; i < image->nr_segments; i++) {
++                      unsigned long mstart, mend;
++                      mstart = image->segment[i].mem;
++                      mend   = mstart + image->segment[i].memsz - 1;
++                      if ((hole_end >= mstart) && (hole_start <= mend)) {
++                              /* Advance the hole to the end of the segment */
++                              hole_start = (mend + (size - 1)) & ~(size - 1);
++                              hole_end   = hole_start + size - 1;
++                              break;
++                      }
++              }
++              /* If I don't overlap any segments I have found my hole! */
++              if (i == image->nr_segments) {
++                      pages = pfn_to_page(hole_start >> PAGE_SHIFT);
++                      break;
++              }
++      }
++      if (pages) {
++              image->control_page = hole_end;
++      }
++      return pages;
++}
++
++
++struct page *kimage_alloc_control_pages(
++      struct kimage *image, unsigned int order)
++{
++      struct page *pages = NULL;
++      switch(image->type) {
++      case KEXEC_TYPE_DEFAULT:
++              pages = kimage_alloc_normal_control_pages(image, order);
++              break;
++      case KEXEC_TYPE_CRASH:
++              pages = kimage_alloc_crash_control_pages(image, order);
++              break;
++      }
++      return pages;
++}
++
++static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
++{
++      if (*image->entry != 0) {
++              image->entry++;
++      }
++      if (image->entry == image->last_entry) {
++              kimage_entry_t *ind_page;
++              struct page *page;
++              page = kimage_alloc_page(image, GFP_KERNEL, KIMAGE_NO_DEST);
++              if (!page) {
++                      return -ENOMEM;
++              }
++              ind_page = page_address(page);
++              *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
++              image->entry = ind_page;
++              image->last_entry =
++                      ind_page + ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
++      }
++      *image->entry = entry;
++      image->entry++;
++      *image->entry = 0;
++      return 0;
++}
++
++static int kimage_set_destination(
++      struct kimage *image, unsigned long destination)
++{
++      int result;
++
++      destination &= PAGE_MASK;
++      result = kimage_add_entry(image, destination | IND_DESTINATION);
++      if (result == 0) {
++              image->destination = destination;
++      }
++      return result;
++}
++
++
++static int kimage_add_page(struct kimage *image, unsigned long page)
++{
++      int result;
++
++      page &= PAGE_MASK;
++      result = kimage_add_entry(image, page | IND_SOURCE);
++      if (result == 0) {
++              image->destination += PAGE_SIZE;
++      }
++      return result;
++}
++
++
++static void kimage_free_extra_pages(struct kimage *image)
++{
++      /* Walk through and free any extra destination pages I may have */
++      kimage_free_page_list(&image->dest_pages);
++
++      /* Walk through and free any unuseable pages I have cached */
++      kimage_free_page_list(&image->unuseable_pages);
++
++}
++static int kimage_terminate(struct kimage *image)
++{
++      if (*image->entry != 0) {
++              image->entry++;
++      }
++      *image->entry = IND_DONE;
++      return 0;
++}
++
++#define for_each_kimage_entry(image, ptr, entry) \
++      for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
++              ptr = (entry & IND_INDIRECTION)? \
++                      phys_to_virt((entry & PAGE_MASK)): ptr +1)
++
++static void kimage_free_entry(kimage_entry_t entry)
++{
++      struct page *page;
++
++      page = pfn_to_page(entry >> PAGE_SHIFT);
++      kimage_free_pages(page);
++}
++
++static void kimage_free(struct kimage *image)
++{
++      kimage_entry_t *ptr, entry;
++      kimage_entry_t ind = 0;
++
++      if (!image)
++              return;
++      kimage_free_extra_pages(image);
++      for_each_kimage_entry(image, ptr, entry) {
++              if (entry & IND_INDIRECTION) {
++                      /* Free the previous indirection page */
++                      if (ind & IND_INDIRECTION) {
++                              kimage_free_entry(ind);
++                      }
++                      /* Save this indirection page until we are
++                       * done with it.
++                       */
++                      ind = entry;
++              }
++              else if (entry & IND_SOURCE) {
++                      kimage_free_entry(entry);
++              }
++      }
++      /* Free the final indirection page */
++      if (ind & IND_INDIRECTION) {
++              kimage_free_entry(ind);
++      }
++
++      /* Handle any machine specific cleanup */
++      machine_kexec_cleanup(image);
++
++      /* Free the kexec control pages... */
++      kimage_free_page_list(&image->control_pages);
++      kfree(image);
++}
++
++static kimage_entry_t *kimage_dst_used(struct kimage *image, unsigned long page)
++{
++      kimage_entry_t *ptr, entry;
++      unsigned long destination = 0;
++
++      for_each_kimage_entry(image, ptr, entry) {
++              if (entry & IND_DESTINATION) {
++                      destination = entry & PAGE_MASK;
++              }
++              else if (entry & IND_SOURCE) {
++                      if (page == destination) {
++                              return ptr;
++                      }
++                      destination += PAGE_SIZE;
++              }
++      }
++      return 0;
++}
++
++static struct page *kimage_alloc_page(struct kimage *image, unsigned int gfp_mask, unsigned long destination)
++{
++      /*
++       * Here we implement safeguards to ensure that a source page
++       * is not copied to its destination page before the data on
++       * the destination page is no longer useful.
++       *
++       * To do this we maintain the invariant that a source page is
++       * either its own destination page, or it is not a
++       * destination page at all.
++       *
++       * That is slightly stronger than required, but the proof
++       * that no problems will not occur is trivial, and the
++       * implementation is simply to verify.
++       *
++       * When allocating all pages normally this algorithm will run
++       * in O(N) time, but in the worst case it will run in O(N^2)
++       * time.   If the runtime is a problem the data structures can
++       * be fixed.
++       */
++      struct page *page;
++      unsigned long addr;
++
++      /*
++       * Walk through the list of destination pages, and see if I
++       * have a match.
++       */
++      list_for_each_entry(page, &image->dest_pages, lru) {
++              addr = page_to_pfn(page) << PAGE_SHIFT;
++              if (addr == destination) {
++                      list_del(&page->lru);
++                      return page;
++              }
++      }
++      page = NULL;
++      while (1) {
++              kimage_entry_t *old;
++
++              /* Allocate a page, if we run out of memory give up */
++              page = kimage_alloc_pages(gfp_mask, 0);
++              if (!page) {
++                      return 0;
++              }
++              /* If the page cannot be used file it away */
++              if (page_to_pfn(page) > (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
++                      list_add(&page->lru, &image->unuseable_pages);
++                      continue;
++              }
++              addr = page_to_pfn(page) << PAGE_SHIFT;
++
++              /* If it is the destination page we want use it */
++              if (addr == destination)
++                      break;
++
++              /* If the page is not a destination page use it */
++              if (!kimage_is_destination_range(image, addr, addr + PAGE_SIZE))
++                      break;
++
++              /*
++               * I know that the page is someones destination page.
++               * See if there is already a source page for this
++               * destination page.  And if so swap the source pages.
++               */
++              old = kimage_dst_used(image, addr);
++              if (old) {
++                      /* If so move it */
++                      unsigned long old_addr;
++                      struct page *old_page;
++
++                      old_addr = *old & PAGE_MASK;
++                      old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
++                      copy_highpage(page, old_page);
++                      *old = addr | (*old & ~PAGE_MASK);
++
++                      /* The old page I have found cannot be a
++                       * destination page, so return it.
++                       */
++                      addr = old_addr;
++                      page = old_page;
++                      break;
++              }
++              else {
++                      /* Place the page on the destination list I
++                       * will use it later.
++                       */
++                      list_add(&page->lru, &image->dest_pages);
++              }
++      }
++      return page;
++}
++
++static int kimage_load_normal_segment(struct kimage *image,
++      struct kexec_segment *segment)
++{
++      unsigned long maddr;
++      unsigned long ubytes, mbytes;
++      int result;
++      unsigned char *buf;
++
++      result = 0;
++      buf = segment->buf;
++      ubytes = segment->bufsz;
++      mbytes = segment->memsz;
++      maddr = segment->mem;
++
++      result = kimage_set_destination(image, maddr);
++      if (result < 0) {
++              goto out;
++      }
++      while(mbytes) {
++              struct page *page;
++              char *ptr;
++              size_t uchunk, mchunk;
++              page = kimage_alloc_page(image, GFP_HIGHUSER, maddr);
++              if (page == 0) {
++                      result  = -ENOMEM;
++                      goto out;
++              }
++              result = kimage_add_page(image, page_to_pfn(page) << PAGE_SHIFT);
++              if (result < 0) {
++                      goto out;
++              }
++              ptr = kmap(page);
++              /* Start with a clear page */
++              memset(ptr, 0, PAGE_SIZE);
++              ptr += maddr & ~PAGE_MASK;
++              mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
++              if (mchunk > mbytes) {
++                      mchunk = mbytes;
++              }
++              uchunk = mchunk;
++              if (uchunk > ubytes) {
++                      uchunk = ubytes;
++              }
++              result = copy_from_user(ptr, buf, uchunk);
++              kunmap(page);
++              if (result) {
++                      result = (result < 0) ? result : -EIO;
++                      goto out;
++              }
++              ubytes -= uchunk;
++              maddr  += mchunk;
++              buf    += mchunk;
++              mbytes -= mchunk;
++      }
++ out:
++      return result;
++}
++
++static int kimage_load_crash_segment(struct kimage *image,
++      struct kexec_segment *segment)
++{
++      /* For crash dumps kernels we simply copy the data from
++       * user space to it's destination.
++       * We do things a page at a time for the sake of kmap.
++       */
++      unsigned long maddr;
++      unsigned long ubytes, mbytes;
++      int result;
++      unsigned char *buf;
++
++      result = 0;
++      buf = segment->buf;
++      ubytes = segment->bufsz;
++      mbytes = segment->memsz;
++      maddr = segment->mem;
++      while(mbytes) {
++              struct page *page;
++              char *ptr;
++              size_t uchunk, mchunk;
++              page = pfn_to_page(maddr >> PAGE_SHIFT);
++              if (page == 0) {
++                      result  = -ENOMEM;
++                      goto out;
++              }
++              ptr = kmap(page);
++              ptr += maddr & ~PAGE_MASK;
++              mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
++              if (mchunk > mbytes) {
++                      mchunk = mbytes;
++              }
++              uchunk = mchunk;
++              if (uchunk > ubytes) {
++                      uchunk = ubytes;
++                      /* Zero the trailing part of the page */
++                      memset(ptr + uchunk, 0, mchunk - uchunk);
++              }
++              result = copy_from_user(ptr, buf, uchunk);
++              kunmap(page);
++              if (result) {
++                      result = (result < 0) ? result : -EIO;
++                      goto out;
++              }
++              ubytes -= uchunk;
++              maddr  += mchunk;
++              buf    += mchunk;
++              mbytes -= mchunk;
++      }
++ out:
++      return result;
++}
++
++static int kimage_load_segment(struct kimage *image,
++      struct kexec_segment *segment)
++{
++      int result = -ENOMEM;
++      switch(image->type) {
++      case KEXEC_TYPE_DEFAULT:
++              result = kimage_load_normal_segment(image, segment);
++              break;
++      case KEXEC_TYPE_CRASH:
++              result = kimage_load_crash_segment(image, segment);
++              break;
++      }
++      return result;
++}
++
++/*
++ * Exec Kernel system call: for obvious reasons only root may call it.
++ *
++ * This call breaks up into three pieces.
++ * - A generic part which loads the new kernel from the current
++ *   address space, and very carefully places the data in the
++ *   allocated pages.
++ *
++ * - A generic part that interacts with the kernel and tells all of
++ *   the devices to shut down.  Preventing on-going dmas, and placing
++ *   the devices in a consistent state so a later kernel can
++ *   reinitialize them.
++ *
++ * - A machine specific part that includes the syscall number
++ *   and the copies the image to it's final destination.  And
++ *   jumps into the image at entry.
++ *
++ * kexec does not sync, or unmount filesystems so if you need
++ * that to happen you need to do that yourself.
++ */
++struct kimage *kexec_image = NULL;
++struct kimage *kexec_crash_image = NULL;
++/*
++ * A home grown binary mutex.
++ * Nothing can wait so this mutex is safe to use
++ * in interrupt context :)
++ */
++static int kexec_lock = 0;
++
++asmlinkage long sys_kexec_load(unsigned long entry,
++      unsigned long nr_segments, struct kexec_segment __user *segments,
++      unsigned long flags)
++{
++      struct kimage **dest_image, *image;
++      int locked;
++      int result;
++
++      /* We only trust the superuser with rebooting the system. */
++      if (!capable(CAP_SYS_BOOT))
++              return -EPERM;
++
++      /*
++       * Verify we have a legal set of flags
++       * This leaves us room for future extensions.
++       */
++      if ((flags & KEXEC_FLAGS) != (flags & ~KEXEC_ARCH_MASK))
++              return -EINVAL;
++
++      /* Verify we are on the appropriate architecture */
++      if (((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH) &&
++              ((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH_DEFAULT))
++      {
++              return -EINVAL;
++      }
++
++      /* Put an artificial cap on the number
++       * of segments passed to kexec_load.
++       */
++      if (nr_segments > KEXEC_SEGMENT_MAX)
++              return -EINVAL;
++
++      image = NULL;
++      result = 0;
++
++      /* Because we write directly to the reserved memory
++       * region when loading crash kernels we need a mutex here to
++       * prevent multiple crash  kernels from attempting to load
++       * simultaneously, and to prevent a crash kernel from loading
++       * over the top of a in use crash kernel.
++       *
++       * KISS: always take the mutex.
++       */
++      locked = xchg(&kexec_lock, 1);
++      if (locked) {
++              return -EBUSY;
++      }
++      dest_image = &kexec_image;
++      if (flags & KEXEC_ON_CRASH) {
++              dest_image = &kexec_crash_image;
++      }
++      if (nr_segments > 0) {
++              unsigned long i;
++              /* Loading another kernel to reboot into */
++              if ((flags & KEXEC_ON_CRASH) == 0) {
++                      result = kimage_normal_alloc(&image, entry, nr_segments, segments);
++              }
++              /* Loading another kernel to switch to if this one crashes */
++              else if (flags & KEXEC_ON_CRASH) {
++                      /* Free any current crash dump kernel before
++                       * we corrupt it.
++                       */
++                      kimage_free(xchg(&kexec_crash_image, NULL));
++                      result = kimage_crash_alloc(&image, entry, nr_segments, segments);
++              }
++              if (result) {
++                      goto out;
++              }
++              result = machine_kexec_prepare(image);
++              if (result) {
++                      goto out;
++              }
++              for(i = 0; i < nr_segments; i++) {
++                      result = kimage_load_segment(image, &image->segment[i]);
++                      if (result) {
++                              goto out;
++                      }
++              }
++              result = kimage_terminate(image);
++              if (result) {
++                      goto out;
++              }
++      }
++      /* Install the new kernel, and  Uninstall the old */
++      image = xchg(dest_image, image);
++
++ out:
++      xchg(&kexec_lock, 0); /* Release the mutex */
++      kimage_free(image);
++      return result;
++}
++
++void crash_kexec(void)
++{
++      struct kimage *image;
++      int locked;
++
++
++      /* Take the kexec_lock here to prevent sys_kexec_load
++       * running on one cpu from replacing the crash kernel
++       * we are using after a panic on a different cpu.
++       *
++       * If the crash kernel was not located in a fixed area
++       * of memory the xchg(&kexec_crash_image) would be
++       * sufficient.  But since I reuse the memory...
++       */
++      locked = xchg(&kexec_lock, 1);
++      if (!locked) {
++              image = xchg(&kexec_crash_image, NULL);
++              if (image) {
++                      machine_crash_shutdown();
++                      machine_kexec(image);
++              }
++              xchg(&kexec_lock, 0);
++      }
++}
+diff -Narup linux-2.4.31-orig/kernel/panic.c linux-2.4.31/kernel/panic.c
+--- linux-2.4.31-orig/kernel/panic.c   2004-11-17 03:54:22.000000000 -0800
++++ linux-2.4.31/kernel/panic.c        2005-08-24 22:40:47.000000000 -0700
+@@ -17,6 +17,7 @@
+ #include <linux/sysrq.h>
+ #include <linux/interrupt.h>
+ #include <linux/console.h>
++#include <linux/kexec.h>
+ asmlinkage void sys_sync(void);       /* it's really int */
+@@ -70,6 +71,11 @@ NORET_TYPE void panic(const char * fmt, 
+               sys_sync();
+       bust_spinlocks(0);
++      /* if we crash and have a crash kernel loaded
++       * let it handle everything else
++       */
++       crash_kexec();
++       
+ #ifdef CONFIG_SMP
+       smp_send_stop();
+ #endif
+diff -Narup linux-2.4.31-orig/kernel/sys.c linux-2.4.31/kernel/sys.c
+--- linux-2.4.31-orig/kernel/sys.c     2003-11-28 10:26:21.000000000 -0800
++++ linux-2.4.31/kernel/sys.c  2005-08-24 23:01:24.000000000 -0700
+@@ -15,6 +15,9 @@
+ #include <linux/init.h>
+ #include <linux/highuid.h>
++#include <linux/kernel.h>
++#include <linux/kexec.h>
++
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+@@ -342,6 +345,21 @@ asmlinkage long sys_reboot(int magic1, i
+               machine_restart(buffer);
+               break;
++      case LINUX_REBOOT_CMD_KEXEC:
++      {
++              struct kimage *image;
++              image = xchg(&kexec_image, 0);
++              if (!image) {
++                      unlock_kernel();
++                      return -EINVAL;
++              }
++              notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
++              printk(KERN_EMERG "Starting new kernel\n");
++              machine_shutdown();
++              machine_kexec(image);
++              break;
++      }
++
+       default:
+               unlock_kernel();
+               return -EINVAL;
diff --git a/kernel/patches-2.4.31/memsize.patch b/kernel/patches-2.4.31/memsize.patch
new file mode 100644 (file)
index 0000000..3ba171e
--- /dev/null
@@ -0,0 +1,26 @@
+diff -Narup linux-2.4.31-orig/arch/ppc/boot/simple/misc-embedded.c linux-2.4.31/arch/ppc/boot/simple/misc-embedded.c
+--- linux-2.4.31-orig/arch/ppc/boot/simple/misc-embedded.c     2006-03-16 23:13:06.000000000 +0800
++++ linux-2.4.31/arch/ppc/boot/simple/misc-embedded.c  2006-03-16 12:43:57.000000000 +0800
+@@ -112,6 +112,9 @@ load_kernel(unsigned long load_addr, int
+       /* Set end of memory available to us.  It is always the highest
+        * memory address provided by the board information.
+        */
++#if defined (CONFIG_REDWOOD_5) || defined (CONFIG_REDWOOD_6)
++      bp->bi_memsize = (16 * 1024 * 1024); // memory limited to 16 MBytes
++#endif 
+       end_avail = (char *)(bp->bi_memsize);
+       puts("\nloaded at:     "); puthex(load_addr);
+diff -Narup linux-2.4.31-orig/arch/ppc/kernel/ppc4xx_setup.c linux-2.4.31/arch/ppc/kernel/ppc4xx_setup.c
+--- linux-2.4.31-orig/arch/ppc/kernel/ppc4xx_setup.c   2006-03-16 23:13:28.000000000 +0800
++++ linux-2.4.31/arch/ppc/kernel/ppc4xx_setup.c        2006-03-16 12:45:35.000000000 +0800
+@@ -161,6 +161,9 @@ ppc4xx_find_end_of_memory(void)
+ {
+       bd_t *bip = (bd_t *) __res;
++#if defined (CONFIG_REDWOOD_5) || defined (CONFIG_REDWOOD_6)
++      bip->bi_memsize = 0x1000000;    // memory was limited 16MB.
++#endif
+       return ((unsigned long) bip->bi_memsize);
+ }
diff --git a/kernel/patches-2.4.31/mvp-version.patch b/kernel/patches-2.4.31/mvp-version.patch
new file mode 100644 (file)
index 0000000..181fede
--- /dev/null
@@ -0,0 +1,43 @@
+diff -Narup -x .DS_Store linux-2.4.31/arch/ppc/boot/simple/head.S linux-2.4.31-mod/arch/ppc/boot/simple/head.S
+--- linux-2.4.31/arch/ppc/boot/simple/head.S   2003-11-28 10:26:19.000000000 -0800
++++ linux-2.4.31-mod/arch/ppc/boot/simple/head.S       2005-09-08 11:09:48.000000000 -0700
+@@ -45,6 +45,25 @@ start:
+       .long   bootrom_cmdline         # address of *bootrom_cmdline
+ #endif
++#ifdef CONFIG_HCW_MVP
++      /* This is a versioning structure for use with the Hauppauge MediaMVP
++       * it is provided with no warranty whatsoever. Use at your own risk.
++       */
++#include <dongle_version.h>
++mvp_start:
++      .long   0x48435720              # structure magic - "HCW MVP" (null terminated)
++      .long   0x4D565000
++      .long   (mvp_end - mvp_start)   # size
++      .long   0x00010000                              # struct version (1.0)
++      .long   HCW_COMPATIBLE_VERSION  # compatible version
++      .long   HCW_BUILD_VERSION               # build version
++      .long   0                                               # reserved[4]
++      .long   0
++      .long   0
++      .long   0
++mvp_end:
++#endif
++
+ start_:
+ #ifdef CONFIG_FORCE
+       /* We have some really bad firmware.  We must disable the L1
+diff -Narup -x .DS_Store linux-2.4.31/arch/ppc/config.in linux-2.4.31-mod/arch/ppc/config.in
+--- linux-2.4.31/arch/ppc/config.in    2005-09-08 11:04:56.000000000 -0700
++++ linux-2.4.31-mod/arch/ppc/config.in        2005-09-08 11:09:01.000000000 -0700
+@@ -81,6 +81,10 @@ if [ "$CONFIG_40x" = "y" ]; then
+    if [ "$CONFIG_EP405" = "y" ]; then
+       bool 'EP405PC Support' CONFIG_EP405PC
+    fi
++   
++   if [ "$CONFIG_REDWOOD_6" = "y" ]; then
++      bool 'Hauppauge MediaMVP support' CONFIG_HCW_MVP
++   fi
+ fi
+ if [ "$CONFIG_44x" = "y" ]; then
diff --git a/kernel/patches-2.4.31/ppc405-wdt.patch b/kernel/patches-2.4.31/ppc405-wdt.patch
new file mode 100644 (file)
index 0000000..ac1e23a
--- /dev/null
@@ -0,0 +1,360 @@
+diff -Narup linux-2.4.31-orig/drivers/char/Config.in linux-2.4.31/drivers/char/Config.in
+--- linux-2.4.31-orig/drivers/char/Config.in   2004-08-07 16:26:04.000000000 -0700
++++ linux-2.4.31/drivers/char/Config.in        2005-08-10 15:01:02.000000000 -0700
+@@ -270,6 +270,7 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then
+       fi
+    fi
+    tristate '  ZF MachZ Watchdog' CONFIG_MACHZ_WDT
++   dep_tristate '  PPC405 Watchdog Timer' CONFIG_PPC405_WDT $CONFIG_4xx
+    if [ "$CONFIG_SGI_IP22" = "y" ]; then
+       dep_tristate '  Indy/I2 Hardware Watchdog' CONFIG_INDYDOG $CONFIG_SGI_IP22
+    fi
+diff -Narup linux-2.4.31-orig/drivers/char/Makefile linux-2.4.31/drivers/char/Makefile
+--- linux-2.4.31-orig/drivers/char/Makefile    2004-08-07 16:26:04.000000000 -0700
++++ linux-2.4.31/drivers/char/Makefile 2005-08-10 15:00:48.000000000 -0700
+@@ -323,6 +323,7 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.
+ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+ obj-$(CONFIG_INDYDOG) += indydog.o
+ obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
++obj-$(CONFIG_PPC405_WDT)  += ppc405_wdt.o
+ subdir-$(CONFIG_MWAVE) += mwave
+ ifeq ($(CONFIG_MWAVE),y)
+diff -Narup linux-2.4.31-orig/drivers/char/ppc405_wdt.c linux-2.4.31/drivers/char/ppc405_wdt.c
+--- linux-2.4.31-orig/drivers/char/ppc405_wdt.c        1969-12-31 16:00:00.000000000 -0800
++++ linux-2.4.31/drivers/char/ppc405_wdt.c     2005-08-10 14:56:02.000000000 -0700
+@@ -0,0 +1,305 @@
++/*
++ * IBM PowerPC 405 Watchdog: A Simple Hardware Watchdog Device
++ * Based on PowerPC 8xx driver by Scott Anderson which was
++ * based on MixCom driver by Gergely Madarasz which was
++ * based on Softdog driver by Alan Cox and PC Watchdog driver by Ken Hollis
++ *
++ * FILE NAME ppc405_wdt.c
++ * 
++ *  Armin Kuster akuster@mvista.com or source@mvista.com
++ *  Sept, 2001
++ *
++ *  Orignial driver
++ *  Author: MontaVista Software, Inc.  <source@mvista.com>
++ *          Debbie Chu   <debbie_chu@mvista.com>
++ *          Frank Rowand <frank_rowand@mvista.com>
++ *
++ * Copyright 2000 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.
++ *
++ *  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.
++ *
++ * Version 0.1 (00/06/05):
++ * Version 0.2 (00/07/12) by Debbie Chu
++ * Version 0.4 (01/09/19) by Armin kuster
++ * Version 0.5 (01/10/10) Akuster
++ *            - removed ppc4xx_restart w/ machine_restart
++ */
++
++#define VERSION "0.5" 
++
++#define WDT_DEFAULT_PERIOD    120     /* system default 2 minutes */
++#define       MAXONEHOUR              3600UL  /* Max timeout period 60 minutes */
++#define       TENMSBASE               10000UL /* 10 ms */
++#define MICROSECBASE          1000000
++  
++#include <linux/module.h>
++#include <linux/config.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/reboot.h>
++#include <linux/init.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/machdep.h>
++
++#define WDIOC_GETPERIOD         _IOR(WATCHDOG_IOCTL_BASE, 6, int)
++#define WDIOC_SETPERIOD         _IOW(WATCHDOG_IOCTL_BASE, 7, int)
++
++int wdt_enable;
++unsigned long wdt_period;
++unsigned long wdt_heartbeat_count;
++static unsigned long wdt_count;
++int wdt_default = 1;
++
++static int ppc405wd_opened;
++
++static inline void
++ppc405wd_update_timer(void)
++{
++      wdt_heartbeat_count = wdt_count; 
++}
++
++void 
++ppc4xx_wdt_heartbeat(void)
++{
++      if (wdt_default ){
++              /* default used until wdt inits */
++              wdt_heartbeat_count = wdt_period * HZ;
++              wdt_default = 0;
++      }       
++      if ((wdt_heartbeat_count > 0) || ( !wdt_enable )) {
++              if (wdt_heartbeat_count > 0)
++                      wdt_heartbeat_count--;
++              mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
++        } else
++              machine_restart("Watchdog Timer Timed out, system reset!");
++      ppc_md.heartbeat_count = 0;
++}
++
++/*
++ *    Allow only one person to hold it open
++ */
++static int ppc405wd_open(struct inode *inode, struct file *file)
++{
++      unsigned int tcr_value;
++
++      if(test_and_set_bit(0,&ppc405wd_opened))
++              return -EBUSY;
++
++      MOD_INC_USE_COUNT;
++
++      /* 
++       * There are three ways to enable the watchdog timer:
++       * 1. turn on the watchdog in the bootrom.
++       * 2. turn on the watchdog using the boot command line option,
++       *    you can specifiy "wdt=<timeout>" on the boot cmdline
++       * 3. turn on the watchdog in this routine,
++       *    the default timer period is set to 2 minutes.
++       */
++
++      tcr_value = mfspr(SPRN_TCR);
++
++      if ((tcr_value & TCR_WRC_MASK) != TCR_WRC(WRC_SYSTEM)) {
++          /* 
++           * watchdog reset not enabled yet, enable it
++           * The default timer period is set to 2 minutes.
++           */
++#ifdef  DEBUG_WDT
++                mtspr(SPRN_TCR,
++                 (mfspr(SPRN_TCR) & ~TCR_WP_MASK & ~TCR_WRC_MASK) |
++                   TCR_WP(WP_2_29) |
++                   TCR_WRC(WRC_SYSTEM));
++#else
++          mtspr(SPRN_TCR,
++                 (mfspr(SPRN_TCR) & ~TCR_WP_MASK & ~TCR_WRC_MASK) |
++                 TCR_WP(WP_2_25) |
++                 TCR_WRC(WRC_SYSTEM));
++#endif
++      }
++
++      if (wdt_period == 0)
++              wdt_period = WDT_DEFAULT_PERIOD;
++
++      wdt_count = wdt_period * HZ;
++      ppc405wd_update_timer();
++      wdt_enable = 1;
++      mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
++      return 0;
++}
++
++static int ppc405wd_release(struct inode *inode, struct file *file)
++{
++      MOD_DEC_USE_COUNT;
++
++      clear_bit(0,&ppc405wd_opened);
++      return 0;
++}
++
++static ssize_t ppc405wd_write(struct file *file, const char *data, size_t len, loff_t *ppos)
++{
++      /*  Can't seek (pwrite) on this device  */
++      if (ppos != &file->f_pos)
++              return -ESPIPE;
++
++      if (len) {
++              ppc405wd_update_timer();
++              return 1;
++      }
++      return 0;
++}
++
++static int ppc405wd_ioctl(struct inode *inode, struct file *file,
++      unsigned int cmd, unsigned long arg)
++{
++      unsigned long period;
++      int status;
++      int state;
++      static struct watchdog_info ident = {
++              WDIOF_KEEPALIVEPING,
++              0,
++              "PPC 405 watchdog"
++      };
++                                        
++      switch (cmd) {
++              case WDIOC_GETSTATUS:
++                      status = ppc405wd_opened;
++
++                      if (copy_to_user((int *)arg, &status, sizeof(int)))
++                              return -EFAULT;
++                      break;
++              case WDIOC_GETSUPPORT:
++                      if (copy_to_user((struct watchdog_info *)arg, &ident, 
++                          sizeof(ident))) {
++                              return -EFAULT;
++                      }
++                      break;
++              case WDIOC_KEEPALIVE:
++                      ppc405wd_update_timer();
++                      break;
++              case WDIOC_SETOPTIONS:
++                      if(copy_from_user(&state, (int*) arg, sizeof(int)))
++                              return -EFAULT;
++                      if (state & WDIOS_DISABLECARD) {
++                              wdt_enable = 0;
++                              printk(KERN_NOTICE "Soft watchdog timer is disabled\n");
++                              break;
++                      }
++                        if (state & WDIOS_ENABLECARD) {
++                              ppc405wd_update_timer();
++                              wdt_enable = 1;
++                              mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
++                              printk(KERN_NOTICE "Soft watchdog timer is enabled\n");
++                              break;
++                      }
++              case WDIOC_GETPERIOD:
++                      /* return watchdog period (units = microseconds) */
++                      period = (wdt_period / HZ) * MICROSECBASE;
++                      if (copy_to_user((unsigned long *)arg, &period, 
++                          sizeof(period))) {
++                              return -EFAULT;
++                      }
++                      break;
++              case WDIOC_SETPERIOD:
++                      /*
++                      ** set watchdog period (units = microseconds)
++                      ** value of zero means maximum
++                      **
++                      ** Don't set a watchdog period to a value less than
++                      ** the requested value (period will be rounded up to
++                      ** next available interval the watchdog supports).
++                      **
++                      ** The software watchdog will expire at some point in
++                      ** the range of (rounded up period) ..
++                      ** (rounded up period + 1 jiffie).  If interrupts are
++                      ** disabled so that the software watchdog is unable to
++                      ** reset the system, then the hardware watchdog will
++                      ** eventually reset the system.
++                      */
++                      if (copy_from_user(&period, (unsigned long *)arg,
++                          sizeof(period))) {
++                              return -EFAULT;
++                      }
++
++                      /* 
++                      ** This code assumes HZ is 100.  Need to remove that
++                      ** assumption.
++                      */
++
++                      /*
++                      ** The minimum period of ppc405wd_timer is a jiffie,
++                      ** which is 10 msec when HZ is 100.  The units of
++                      ** wdt_period is jiffies.
++                      **
++                      ** The new timer period will be used at the next
++                      ** heartbeat.
++                      */
++                      if (period == 0)
++                              period = MAXONEHOUR * MICROSECBASE;        
++
++                      wdt_count = (period / TENMSBASE) + (period % TENMSBASE ? 1 : 0);
++                      ppc405wd_update_timer();
++
++                      break;
++              default:
++                      return -ENOIOCTLCMD;
++
++      }
++      return 0;
++}
++
++static struct file_operations ppc405wd_fops =
++{
++      owner:          THIS_MODULE,
++      write:          ppc405wd_write,
++      ioctl:          ppc405wd_ioctl,
++      open:           ppc405wd_open,
++      release:        ppc405wd_release,
++};
++
++static struct miscdevice ppc405wd_miscdev =
++{
++      WATCHDOG_MINOR,
++      "405_watchdog",
++      &ppc405wd_fops
++};
++
++static int __init ppc405wd_init(void)
++{
++      misc_register(&ppc405wd_miscdev);
++      printk(KERN_NOTICE "PPC 405 watchdog driver v%s\n", VERSION);
++      if (wdt_period == 0)
++              wdt_period = WDT_DEFAULT_PERIOD;
++      wdt_count = wdt_period * HZ;
++      ppc405wd_update_timer();
++      mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
++      mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
++      return 0;
++}     
++
++void __exit ppc405wd_exit(void)
++{
++      misc_deregister(&ppc405wd_miscdev);
++}
++
++module_init(ppc405wd_init);
++module_exit(ppc405wd_exit);
+diff -Narup linux-2.4.31-orig/include/asm-ppc/machdep.h linux-2.4.31/include/asm-ppc/machdep.h
+--- linux-2.4.31-orig/include/asm-ppc/machdep.h        2003-08-25 04:44:44.000000000 -0700
++++ linux-2.4.31/include/asm-ppc/machdep.h     2005-08-10 15:13:37.000000000 -0700
+@@ -41,6 +41,8 @@ struct machdep_calls {
+       unsigned long   (*get_rtc_time)(void);
+       void            (*calibrate_decr)(void);
+       void            (*heartbeat)(void);
++      unsigned long   heartbeat_reset;
++      unsigned long   heartbeat_count;
+       unsigned long   (*find_end_of_memory)(void);
+       void            (*setup_io_mappings)(void);
+diff -Narup linux-2.4.31-orig/include/asm-ppc/processor.h linux-2.4.31/include/asm-ppc/processor.h
+--- linux-2.4.31-orig/include/asm-ppc/processor.h      2005-04-03 18:42:20.000000000 -0700
++++ linux-2.4.31/include/asm-ppc/processor.h   2005-08-10 15:10:17.000000000 -0700
+@@ -455,11 +455,13 @@
+ #define           WP_2_21             1               /* 2^21 clocks */
+ #define           WP_2_25             2               /* 2^25 clocks */
+ #define           WP_2_29             3               /* 2^29 clocks */
++#define   TCR_WP_MASK           TCR_WP(3)
+ #define         TCR_WRC(x)            (((x)&0x3)<<28) /* WDT Reset Control */
+ #define           WRC_NONE            0               /* No reset will occur */
+ #define           WRC_CORE            1               /* Core reset will occur */
+ #define           WRC_CHIP            2               /* Chip reset will occur */
+ #define           WRC_SYSTEM          3               /* System reset will occur */
++#define   TCR_WRC_MASK          TCR_WRC(3)
+ #define         TCR_WIE               0x08000000      /* WDT Interrupt Enable */
+ #define         TCR_PIE               0x04000000      /* PIT Interrupt Enable */
+ #define         TCR_DIE               TCR_PIE         /* DEC Interrupt Enable */
diff --git a/kernel/patches-2.4.31/redwood.c b/kernel/patches-2.4.31/redwood.c
new file mode 100644 (file)
index 0000000..7619e85
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * redwood.c - mapper for IBM Redwood-4/5/6 board.
+ *
+ *
+ * Copyright 2001 - 2002 MontaVista Softare Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ *  THIS  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.
+ *
+ *  History: 12/17/2001 - Armin
+ *             migrated to use do_map_probe
+ *
+ *             : 07/11/02 - Armin
+ *             added redwood 6 support
+ *
+ */
+
+#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>
+#define STBXX_VPD_SZ   0x10000
+#define STBXX_OB_SZ    0x20000
+#define STBXX_4MB      0x4000000
+
+#if !defined (CONFIG_REDWOOD_6)
+
+#define WINDOW_ADDR 0xffc00000
+#define WINDOW_SIZE 0x00400000
+
+#define RW_PART0_OF    0
+#define RW_PART0_SZ    0x10000
+#define RW_PART1_OF    RW_PART0_SZ     
+#define RW_PART1_SZ    0x200000 - 0x10000
+#define RW_PART2_OF    0x200000        
+#define RW_PART2_SZ    0x10000
+#define RW_PART3_OF    0x210000        
+#define RW_PART3_SZ    0x200000 - (0x10000 + 0x20000)  
+#define RW_PART4_OF    0x3e0000
+#define RW_PART4_SZ    0x20000 
+static struct mtd_partition redwood_flash_partitions[] = {
+       {
+               name: "Redwood OpenBIOS Vital Product Data",
+               offset: RW_PART0_OF,
+               size: RW_PART0_SZ,
+               mask_flags: MTD_WRITEABLE       /* force read-only */
+       },
+       {
+               name: "Redwood kernel",
+               offset: RW_PART1_OF,
+               size: RW_PART1_SZ
+       },
+       {
+               name: "Redwood OpenBIOS non-volatile storage",
+               offset: RW_PART2_OF,
+               size: RW_PART2_SZ,
+               mask_flags: MTD_WRITEABLE       /* force read-only */
+       },
+       {
+               name: "Redwood filesystem",
+               offset: RW_PART3_OF,
+               size: RW_PART3_SZ
+       },
+       {
+               name: "Redwood OpenBIOS",
+               offset: RW_PART4_OF,
+               size: RW_PART4_SZ,
+               mask_flags: MTD_WRITEABLE       /* force read-only */
+       }
+};
+
+#else
+
+/* FIXME: the window is bigger - armin */
+
+/*
+ * Change4VideoDongle - H. Lin
+ * Warnning: What effects would be if not end on erase block size??
+ * Thus combine VPD,NVRAM,into one 64KB partition, named VPD
+ */
+#if 1  //hcw
+
+/* Supported Devices on HCW MediaMVP */
+#define AMD2048X16K
+#define AMD512X16K
+
+#ifdef AMD2048X16K
+
+#define MB4_WINDOW_ADDR 0xffc00000                             /* 4MB part */
+#define MB4_WINDOW_SIZE 0x00400000                             /* to hook GPIO Pin26 (BI_ADDR10) to A20 */
+
+#define MB4_RW_PART0_OF        0x000000                                
+#define MB4_RW_PART0_SZ        0x2c0000                                
+/*
+#define MB4_RW_PART0_SZ        0x2c0000                                
+
+#define MB4_RW_PART5_OF        MB4_RW_PART0_OF + MB4_RW_PART0_SZ
+#define MB4_RW_PART5_SZ        0x200000                                        
+
+#define MB4_RW_PART4_OF        MB4_RW_PART5_OF + MB4_RW_PART5_SZ
+*/
+#define MB4_RW_PART4_OF        MB4_RW_PART0_OF + MB4_RW_PART0_SZ
+#define MB4_RW_PART4_SZ        0x100000                                        
+
+#define MB4_RW_PART1_OF        MB4_RW_PART4_OF + MB4_RW_PART4_SZ
+#define MB4_RW_PART1_SZ        0x010000                                        /* 64KB VPD = 4KB VPD + 4KB NVRAM */
+
+#define MB4_RW_PART2_OF        MB4_RW_PART1_OF + MB4_RW_PART1_SZ
+#define MB4_RW_PART2_SZ        0x010000                                        /* 64KB LOGO = 56KB LOGO + 8KB XXX */
+
+#define MB4_RW_PART3_OF        MB4_RW_PART2_OF + MB4_RW_PART2_SZ       /* 128KB Bootloader(Open BIOS) */
+#define MB4_RW_PART3_SZ        0x020000
+
+static struct mtd_partition mb4_redwood_flash_partitions[] = {
+       {
+               name: "HCW MediaMVP KERN",
+               offset: MB4_RW_PART0_OF,
+               size: MB4_RW_PART0_SZ,
+       },
+/*
+       {
+               name: "HCW MediaMVP FS",
+               offset: MB4_RW_PART5_OF,
+               size: MB4_RW_PART5_SZ,
+       },
+*/     
+       {
+               name: "HCW MediaMVP DATA",
+               offset: MB4_RW_PART4_OF,
+               size: MB4_RW_PART4_SZ,                  
+       },
+       {
+               name: "HCW MediaMVP VPD",
+               offset: MB4_RW_PART1_OF,
+               size: MB4_RW_PART1_SZ,
+       },
+       {
+               name: "HCW MediaMVP LOGO",
+               offset: MB4_RW_PART2_OF,
+               size: MB4_RW_PART2_SZ,
+       },
+       {
+               name: "HCW MediaMVP BOOT",
+               offset: MB4_RW_PART3_OF,
+               size: MB4_RW_PART3_SZ,
+       }
+};
+
+#endif
+
+
+#ifdef AMD512X16K
+
+#define MB1_WINDOW_ADDR 0xfff00000
+#define MB1_WINDOW_SIZE 0x00100000
+
+#define MB1_RW_PART0_OF        0
+#define MB1_RW_PART0_SZ        0x80000                                 /* 8*64 = 512KB data */
+
+#define MB1_RW_PART1_OF        MB1_RW_PART0_OF + MB1_RW_PART0_SZ
+#define MB1_RW_PART1_SZ        0x10000                                 /* 64KB VPD = 4KB VPD + 4KB NVRAM */
+
+#define MB1_RW_PART2_OF        MB1_RW_PART1_OF + MB1_RW_PART1_SZ
+#define MB1_RW_PART2_SZ        0x10000                                 /* 64KB LOGO = 56KB LOGO + 8KB XXX */
+
+#define MB1_RW_PART3_OF        MB1_RW_PART2_OF + MB1_RW_PART2_SZ       
+#define MB1_RW_PART3_SZ        0x80000-0x20000-0x20000                 /* 320 - 64 = 256KB File System */
+
+#define MB1_RW_PART4_OF        MB1_RW_PART3_OF + MB1_RW_PART3_SZ       /* 128KB Bootloader(Open BIOS) */
+#define MB1_RW_PART4_SZ        0x20000
+
+static struct mtd_partition mb1_redwood_flash_partitions[] = {
+       {
+               name: "HCW MediaMVP KERN",
+               offset: MB1_RW_PART0_OF,
+               size: MB1_RW_PART0_SZ,
+       },
+       {
+               name: "HCW MediaMVP VPD",
+               offset: MB1_RW_PART1_OF,
+               size: MB1_RW_PART1_SZ,
+               //mask_flags: MTD_WRITEABLE     /* force read-only */
+       },
+       {
+               name: "HCW MediaMVP LOGO",
+               offset: MB1_RW_PART2_OF,
+               size: MB1_RW_PART2_SZ,
+               //mask_flags: MTD_WRITEABLE     /* force read-only */
+       },
+       {
+               name: "HCW MediaMVP FS",
+               offset: MB1_RW_PART3_OF,
+               size: MB1_RW_PART3_SZ,
+       },
+       {
+               name: "HCW MediaMVP BOOT",
+               offset: MB1_RW_PART4_OF,
+               size: MB1_RW_PART4_SZ,
+               //mask_flags: MTD_WRITEABLE     /* force read-only */
+       }
+};
+#endif
+
+#ifdef AMD128X16K
+
+#define MBQ_WINDOW_ADDR 0xfffC0000
+#define MBQ_WINDOW_SIZE 0x00040000
+
+#define MBQ_RW_PART0_OF        0
+#define MBQ_RW_PART0_SZ        0x10000         /* 64KB VPD (4KB VPD + 4KB NVRAM) */
+
+#define MBQ_RW_PART1_OF        MBQ_RW_PART0_OF + MBQ_RW_PART0_SZ
+#define MBQ_RW_PART1_SZ        0x10000         /* 64KB Logo */
+
+#define MBQ_RW_PART2_OF        MBQ_RW_PART1_OF + MBQ_RW_PART1_SZ
+#define MBQ_RW_PART2_SZ        0x20000         /* 128KB Bootloader(Open BIOS) */
+
+
+static struct mtd_partition mbq_redwood_flash_partitions[] = {
+       {
+               name: "HCW MediaMVP VPD",
+               offset: MBQ_RW_PART0_OF,
+               size: MBQ_RW_PART0_SZ,
+               //mask_flags: MTD_WRITEABLE     /* force read-only */
+       },
+       {
+               name: "HCW MediaMVP LOGO",
+               offset: MBQ_RW_PART1_OF,
+               size: MBQ_RW_PART1_SZ,
+               //mask_flags: MTD_WRITEABLE     /* force read-only */
+       },
+       {
+               name: "HCW MediaMVP BOOT",
+               offset: MBQ_RW_PART2_OF,
+               size: MBQ_RW_PART2_SZ,
+               //mask_flags: MTD_WRITEABLE     /* force read-only */
+       }
+};
+
+#endif
+
+#else  //org
+
+#define WINDOW_ADDR 0xff800000
+#define WINDOW_SIZE 0x00800000
+
+#define RW_PART0_OF    0
+#define RW_PART0_SZ    0x400000        /* 4 MB data */
+#define RW_PART1_OF    RW_PART0_OF + RW_PART0_SZ       
+#define RW_PART1_SZ    0x10000         /* 64K VPD */
+#define RW_PART2_OF    RW_PART1_OF + RW_PART1_SZ       
+#define RW_PART2_SZ    0x400000 - (0x10000 + 0x20000)  
+#define RW_PART3_OF    RW_PART2_OF + RW_PART2_SZ
+#define RW_PART3_SZ    0x20000
+
+static struct mtd_partition redwood_flash_partitions[] = {
+       {
+               name: "Redwood kernel",
+               offset: RW_PART0_OF,
+               size: RW_PART0_SZ
+       },
+       {
+               name: "Redwood OpenBIOS Vital Product Data",
+               offset: RW_PART1_OF,
+               size: RW_PART1_SZ,
+               mask_flags: MTD_WRITEABLE       /* force read-only */
+       },
+       {
+               name: "Redwood filesystem",
+               offset: RW_PART2_OF,
+               size: RW_PART2_SZ
+       },
+       {
+               name: "Redwood OpenBIOS",
+               offset: RW_PART3_OF,
+               size: RW_PART3_SZ,
+               mask_flags: MTD_WRITEABLE       /* force read-only */
+       }
+};
+
+#endif
+
+#endif
+
+__u8 redwood_flash_read8(struct map_info *map, unsigned long ofs)
+{
+       return *(__u8 *)(map->map_priv_1 + ofs);
+}
+
+__u16 redwood_flash_read16(struct map_info *map, unsigned long ofs)
+{
+       return *(__u16 *)(map->map_priv_1 + ofs);
+}
+
+__u32 redwood_flash_read32(struct map_info *map, unsigned long ofs)
+{
+       return *(volatile unsigned int *)(map->map_priv_1 + ofs);
+}
+
+void redwood_flash_copy_from(struct map_info *map, void *to,
+               unsigned long from, ssize_t len)
+{
+       memcpy(to, (void *)(map->map_priv_1 + from), len);
+}
+
+void redwood_flash_write8(struct map_info *map, __u8 d, unsigned long adr)
+{
+       *(__u8 *)(map->map_priv_1 + adr) = d;
+}
+
+void redwood_flash_write16(struct map_info *map, __u16 d, unsigned long adr)
+{
+       *(__u16 *)(map->map_priv_1 + adr) = d;
+}
+
+void redwood_flash_write32(struct map_info *map, __u32 d, unsigned long adr)
+{
+       *(__u32 *)(map->map_priv_1 + adr) = d;
+}
+
+void redwood_flash_copy_to(struct map_info *map, unsigned long to,
+               const void *from, ssize_t len)
+{
+       memcpy((void *)(map->map_priv_1 + to), from, len);
+}
+
+
+
+struct map_info redwood_flash_map = {
+       name: "HCW MediaMVP",
+//     size: WINDOW_SIZE,
+       buswidth: 2,
+       read8: redwood_flash_read8,
+       read16: redwood_flash_read16,
+       read32: redwood_flash_read32,
+       copy_from: redwood_flash_copy_from,
+       write8: redwood_flash_write8,
+       write16: redwood_flash_write16,
+       write32: redwood_flash_write32,
+       copy_to: redwood_flash_copy_to
+};
+
+#define NUM_REDWOOD_FLASH_PARTITIONS(flash_partitions) \
+       (sizeof(flash_partitions)/sizeof((flash_partitions)[0]))
+
+
+static struct mtd_info *redwood_mtd;
+
+int __init init_redwood_flash(void)
+{
+       int numparts;
+       struct mtd_partition *redwood_flash_partitions;
+
+#ifdef AMD512X16K
+       /*
+        * Am29LV800/200BT does NOT seem to do CFI
+        */
+       redwood_flash_map.map_priv_1 =
+               (unsigned long)ioremap(MB1_WINDOW_ADDR, MB1_WINDOW_SIZE);
+
+       if (!redwood_flash_map.map_priv_1) {
+               printk("init_redwood_flash: failed to ioremap\n");
+               return -EIO;
+       }
+
+       printk(KERN_NOTICE "HCW MediaMVP: flash mapping: %x at %x to %lx\n",
+                       MB1_WINDOW_SIZE, MB1_WINDOW_ADDR, redwood_flash_map.map_priv_1);
+
+       redwood_flash_map.size = MB1_WINDOW_SIZE;
+       redwood_mtd = do_map_probe("jedec_probe",&redwood_flash_map);
+       if(redwood_mtd) {
+               printk("jedec_probe: found redwood_mtd size = %08x\n", redwood_mtd->size);
+               if( redwood_mtd->size == 0x00100000 ) {
+                       redwood_flash_partitions = mb1_redwood_flash_partitions;
+                       numparts = NUM_REDWOOD_FLASH_PARTITIONS(mb1_redwood_flash_partitions);
+                       printk(KERN_NOTICE "HCW MediaMVP: jedec_probe: add [%d]parts\n", numparts);
+                       goto add_parts;
+               } else {
+                       map_destroy( redwood_mtd );
+               }
+       }
+       printk(KERN_NOTICE "HCW MediaMVP: jedec_probe: no known JEDEC part found\n");
+       iounmap((void*)(redwood_flash_map.map_priv_1));
+
+try_4mb_flash:
+#endif
+
+#ifdef AMD2048X16K
+
+       redwood_flash_map.map_priv_1 =
+               (unsigned long)ioremap(MB4_WINDOW_ADDR, MB4_WINDOW_SIZE);
+
+       if (!redwood_flash_map.map_priv_1) {
+               printk("init_redwood_flash: failed to ioremap\n");
+               return -EIO;
+       }
+
+       printk(KERN_NOTICE "HCW MediaMVP: flash mapping: %x at %x to %lx\n",
+                       MB4_WINDOW_SIZE, MB4_WINDOW_ADDR, redwood_flash_map.map_priv_1);
+
+#if 1  
+       /*
+        * do CFI for 320DT 
+        */
+       redwood_flash_map.size = MB4_WINDOW_SIZE;
+       redwood_mtd = do_map_probe("cfi_probe",&redwood_flash_map);
+       if(redwood_mtd) {
+               printk("cfi_probe: found redwood_mtd size = %08x\n", redwood_mtd->size);
+               redwood_flash_partitions = mb4_redwood_flash_partitions;
+               numparts = NUM_REDWOOD_FLASH_PARTITIONS(mb4_redwood_flash_partitions);
+               printk(KERN_NOTICE "HCW MediaMVP: cfi_probe: adding [%d]parts\n", numparts);
+               goto add_parts;
+       }
+       else {
+               printk(KERN_NOTICE "HCW MediaMVP: cfi_probe: no known CFI part found\n");
+               iounmap((void*)(redwood_flash_map.map_priv_1));
+       }
+#endif
+       
+#if 0 
+       /*
+        * try jedec too for ST320DT???
+        */
+       redwood_flash_map.map_priv_1 =
+               (unsigned long)ioremap(MB4_WINDOW_ADDR, MB4_WINDOW_SIZE);
+
+       if (!redwood_flash_map.map_priv_1) {
+               printk("init_redwood_flash: failed to ioremap\n");
+               return -EIO;
+       }
+
+       printk(KERN_NOTICE "HCW MediaMVP: flash mapping: %x at %x to %lx\n",
+                       MB4_WINDOW_SIZE, MB4_WINDOW_ADDR, redwood_flash_map.map_priv_1);
+
+       redwood_flash_map.size = MB4_WINDOW_SIZE;
+       redwood_mtd = do_map_probe("jedec_probe",&redwood_flash_map);
+       if(redwood_mtd) {
+               printk("jedec_probe: found redwood_mtd size = %08x\n", redwood_mtd->size);
+               redwood_flash_partitions = mb4_redwood_flash_partitions;
+               numparts = NUM_REDWOOD_FLASH_PARTITIONS(mb4_redwood_flash_partitions);
+               printk(KERN_NOTICE "HCW MediaMVP: jedec_probe: adding [%d]parts\n", numparts);
+               goto add_parts;
+       }
+       else {
+               printk(KERN_NOTICE "HCW MediaMVP: jedec_probe: no known CFI part found\n");
+               iounmap((void*)(redwood_flash_map.map_priv_1));
+       }
+#endif
+#endif
+
+
+add_parts:
+       if (redwood_mtd) {
+               redwood_mtd->module = THIS_MODULE;
+               return add_mtd_partitions(redwood_mtd, redwood_flash_partitions, numparts);
+       }
+
+       return -ENXIO;
+}
+
+static void __exit cleanup_redwood_flash(void)
+{
+       if (redwood_mtd) {
+               del_mtd_partitions(redwood_mtd);
+               /* moved iounmap after map_destroy  -armin*/
+               map_destroy(redwood_mtd);
+               iounmap((void *)redwood_flash_map.map_priv_1);
+       }
+}
+
+module_init(init_redwood_flash);
+module_exit(cleanup_redwood_flash);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Armin Kuster <akuster@mvista.com>");
+MODULE_DESCRIPTION("MTD map driver for the IBM Redwood reference boards");
diff --git a/kernel/patches-2.4.31/sdram-bank1.patch b/kernel/patches-2.4.31/sdram-bank1.patch
new file mode 100644 (file)
index 0000000..203022c
--- /dev/null
@@ -0,0 +1,266 @@
+diff -Narup linux-2.4.31-orig/arch/ppc/boot/simple/Makefile linux-2.4.31/arch/ppc/boot/simple/Makefile
+--- linux-2.4.31-orig/arch/ppc/boot/simple/Makefile    2005-12-14 15:16:26.000000000 +0800
++++ linux-2.4.31/arch/ppc/boot/simple/Makefile 2006-01-15 17:28:42.000000000 +0800
+@@ -152,6 +152,7 @@ zImage: $(ZIMAGE)
+       rm -f zvmlinux
+ zImage.initrd: $(ZIMAGEINITRD)
+       rm -f zvmlinux.initrd
++      cp -f ../images/zImage.initrd.$(END) $(INSTALL_PATH)/dongle.bin
+ znetboot: zImage
+       cp ../images/zImage.$(END) $(TFTPIMAGE)
+diff -Narup linux-2.4.31-orig/arch/ppc/boot/simple/misc-embedded.c linux-2.4.31/arch/ppc/boot/simple/misc-embedded.c
+--- linux-2.4.31-orig/arch/ppc/boot/simple/misc-embedded.c     2005-12-14 16:27:53.000000000 +0800
++++ linux-2.4.31/arch/ppc/boot/simple/misc-embedded.c  2006-01-15 17:28:42.000000000 +0800
+@@ -221,6 +221,7 @@ load_kernel(unsigned long load_addr, int
+       gunzip(0, 0x400000, zimage_start, &zimage_size);
+       flush_instruction_cache();
+       puts("done.\n");
++#ifdef CONFIG_BLK_DEV_INITRD
+       {
+               struct bi_record *rec;
+               unsigned long initrd_loc;
+@@ -271,6 +272,31 @@ load_kernel(unsigned long load_addr, int
+               rec->size = sizeof(struct bi_record);
+               rec = (struct bi_record *)((unsigned long)rec + rec->size);
+       }
++#else
++      {
++              /* Moving Squash Rootfs to sdram bank1 */
++              if(initrd_size){
++                      #define MAGIC_VER_HCW           0x48435720
++                      #define MAGIC_VER_MVP           0x4D565000
++                      unsigned long *magic_hcw;
++                      unsigned long *magic_mvp;
++                      unsigned long *initrd_sz;
++                      
++                      magic_hcw = 0xa0fff200;
++                      magic_mvp = 0xa0fff204;
++                      /* if there is no magic number on new xram_start + 512 bytes, we assume 
++                       * system boot first time then move boot data into new xram position. */
++                      if( *magic_hcw != MAGIC_VER_HCW && *magic_mvp != MAGIC_VER_MVP ){
++                              puts("\nMoving xram data to 0xa0fff000\n");
++                              memcpy((void*)(0xa0fff000), (void*)(0xa0f00000), 0x1000);       
++                      }
++                      puts("Moving initrd to 0xa0d00000\n");
++                      memcpy((void*)(0xa0d00000), &__ramdisk_begin, initrd_size);
++                      /* writing initrd size into bottom of bank1 memory */
++                      memcpy((void*)0xa0fffffc, &initrd_size, 4);
++              }
++      }
++#endif
+       puts("Now booting the kernel\n");
+       serial_close(com_port);
+diff -Narup linux-2.4.31-orig/drivers/mtd/maps/Config.in linux-2.4.31/drivers/mtd/maps/Config.in
+--- linux-2.4.31-orig/drivers/mtd/maps/Config.in       2005-12-14 15:16:07.000000000 +0800
++++ linux-2.4.31/drivers/mtd/maps/Config.in    2006-01-15 17:28:22.000000000 +0800
+@@ -45,6 +45,7 @@ if [ "$CONFIG_PPC" = "y" ]; then
+    dep_tristate '  CFI Flash device mapped on D-Box2' CONFIG_MTD_DBOX2 $CONFIG_MTD_CFI
+    dep_tristate '  CFI Flash device mapping on FlagaDM' CONFIG_MTD_CFI_FLAGADM $CONFIG_MTD_CFI
+    dep_tristate '  CFI Flash device mapped on IBM Redwood-4/5' CONFIG_MTD_REDWOOD $CONFIG_MTD_CFI
++   dep_tristate '  SDRAM device mapping on Hauppauge MVP' CONFIG_MTD_MVP_RAM $CONFIG_MTD_CFI
+ fi
+ if [ "$CONFIG_MIPS" = "y" ]; then
+diff -Narup linux-2.4.31-orig/drivers/mtd/maps/Makefile linux-2.4.31/drivers/mtd/maps/Makefile
+--- linux-2.4.31-orig/drivers/mtd/maps/Makefile        2005-12-14 15:16:07.000000000 +0800
++++ linux-2.4.31/drivers/mtd/maps/Makefile     2006-01-15 17:28:22.000000000 +0800
+@@ -61,5 +61,6 @@ obj-$(CONFIG_MTD_REDWOOD)    += redwood.o
+ obj-$(CONFIG_MTD_UCLINUX)     += uclinux.o
+ obj-$(CONFIG_MTD_NETtel)      += nettel.o
+ obj-$(CONFIG_MTD_SCB2_FLASH)  += scb2_flash.o
++obj-$(CONFIG_MTD_MVP_RAM)       += ramdisk.o
+ include $(TOPDIR)/Rules.make
+diff -Narup linux-2.4.31-orig/drivers/mtd/maps/ramdisk.c linux-2.4.31/drivers/mtd/maps/ramdisk.c
+--- linux-2.4.31-orig/drivers/mtd/maps/ramdisk.c       1970-01-01 08:00:00.000000000 +0800
++++ linux-2.4.31/drivers/mtd/maps/ramdisk.c    2006-01-15 17:28:22.000000000 +0800
+@@ -0,0 +1,187 @@
++/*
++ * HCW sdram mtd Driver
++ */
++#include <linux/config.h>
++#include <linux/version.h>
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++
++#if CONFIG_MODVERSIONS == 1
++#define MODVERSIONS
++#include <linux/modversions.h>
++#endif
++
++#include <linux/fs.h>
++#include <asm/io.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/errno.h>
++#include <asm/uaccess.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++
++#define KDBG(fmt, args...) if(1) printk("<sdram-mtd>: " fmt, ## args)
++
++
++#define __PHYSICAL_ROOTFS_BASE                0xA0D00000
++#define __PHYSICAL_ROOTFS_SIZE_BASE   0xA0FFFFFC
++#define __PHYSICAL_ROOTFS_END_BASE    0xA0FFF000
++#define __PHYSICAL_TOTAL_SIZE         0x002FF000
++
++#define GetRootSize() {return (*rootfs_size)}
++
++
++//
++// read/write function.
++//
++static __u8 sdram_read8(struct map_info *map, unsigned long ofs)
++{
++      return readb(map->map_priv_1 + ofs);
++}
++
++static __u16 sdram_read16(struct map_info *map, unsigned long ofs)
++{
++      return readw(map->map_priv_1 + ofs);
++}
++
++static __u32 sdram_read32(struct map_info *map, unsigned long ofs)
++{
++      return readl(map->map_priv_1 + ofs);
++}
++
++static void sdram_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
++{
++      memcpy(to, (void *)(map->map_priv_1 + from), len);
++}     
++
++static void sdram_write8(struct map_info *map, __u8 d, unsigned long adr)
++{
++      writeb(d, map->map_priv_1 + adr);
++}
++
++static void sdram_write16(struct map_info *map, __u16 d, unsigned long adr)
++{
++      writew(d, map->map_priv_1 + adr);
++}
++
++static void sdram_write32(struct map_info *map, __u32 d, unsigned long adr)
++{
++      writel(d, map->map_priv_1 + adr);
++}
++
++static void sdram_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
++{
++      memcpy((void *)(map->map_priv_1 + to), from, len);
++}
++
++static struct mtd_partition hcwmvp_sdram_partitions[] = {
++      {
++              name: "HCW MediaMVP ROOT",      
++              offset: 0x00000000      ,
++      },
++      {
++              name: "HCW MediaMVP OSD",
++      },
++};
++
++//
++// sdram mtd map structure.
++//
++struct map_info hcwmvp_sdram_map = {
++      name:"SDRAM MTD Device",
++      buswidth: 2,
++      read8: sdram_read8,
++      read16: sdram_read16,
++      read32: sdram_read32,
++      copy_from: sdram_copy_from,
++      write8: sdram_write8,
++      write16: sdram_write16,
++      write32: sdram_write32,
++      copy_to: sdram_copy_to
++};
++static struct mtd_info *hcwmvp_sdram_mtd=NULL;
++
++static unsigned long 
++sdram_init(void)
++{
++      /*
++       * I/O Remap
++       */
++      hcwmvp_sdram_map.map_priv_1 =  
++              (unsigned long)ioremap(__PHYSICAL_ROOTFS_BASE,  __PHYSICAL_TOTAL_SIZE);
++      if (!hcwmvp_sdram_map.map_priv_1) {
++              KDBG("sdram-1 MTD device map failed\n");
++              return 0;
++      }
++      hcwmvp_sdram_map.map_priv_2 = (unsigned long)ioremap(__PHYSICAL_ROOTFS_SIZE_BASE,  4);
++      if (!hcwmvp_sdram_map.map_priv_2) {
++              KDBG("sdram-2 MTD device map failed\n");
++              return 0;
++      }
++      
++      KDBG("SDRAM MTD(%8.8X) mapped to %08x\n", (int)__PHYSICAL_ROOTFS_BASE, (int)hcwmvp_sdram_map.map_priv_1);
++
++      return 1;
++}
++
++/*
++ * module interface
++ */
++static int __init
++sdram_init_module(void)
++{
++      unsigned int root_size=0;
++      /*
++       * Probe & reset Device
++       */
++      if(!sdram_init()) {
++              KDBG("sdram Module Init Failed: Wrong Dev\n");
++              return -1;
++      }
++      
++      /*
++       * register mtd device 
++       */
++      hcwmvp_sdram_map.size = __PHYSICAL_TOTAL_SIZE;
++      hcwmvp_sdram_mtd = do_map_probe("map_ram",&hcwmvp_sdram_map);
++      if (hcwmvp_sdram_mtd) {
++              hcwmvp_sdram_mtd->module = THIS_MODULE;
++              //hcwmvp_sdram_mtd->erasesize = 0xF0000;
++              //add_mtd_device(hcwmvp_sdram_mtd);
++              root_size = in_be32((u32*)hcwmvp_sdram_map.map_priv_2);
++              //root_size |= in_be16((u16*)(hcwmvp_sdram_map.map_priv_2+2));
++              //KDBG("root_size =%x \n", root_size);
++              hcwmvp_sdram_partitions[0].size = root_size;
++              hcwmvp_sdram_partitions[1].offset = root_size;
++              hcwmvp_sdram_partitions[1].size = __PHYSICAL_TOTAL_SIZE -  root_size;
++              add_mtd_partitions(hcwmvp_sdram_mtd, hcwmvp_sdram_partitions, 2);
++      }
++      else{
++              iounmap((void*)(hcwmvp_sdram_map.map_priv_1));
++      }
++
++      return 0;
++}
++
++static void __exit
++sdram_cleanup_module(void)
++{
++      /* unregister mtd device. */
++      //if (hcwmvp_sdram_mtd) del_mtd_device(hcwmvp_sdram_mtd);
++      if (hcwmvp_sdram_mtd){
++               del_mtd_partitions(hcwmvp_sdram_mtd);
++               map_destroy(hcwmvp_sdram_mtd);
++      }
++      if (hcwmvp_sdram_map.map_priv_1 != -1) iounmap((void *)hcwmvp_sdram_map.map_priv_1);
++}
++module_init(sdram_init_module);
++module_exit(sdram_cleanup_module);
++MODULE_LICENSE("GPL");
diff --git a/kernel/patches-2.4.31/smc91111.patch b/kernel/patches-2.4.31/smc91111.patch
new file mode 100644 (file)
index 0000000..27b520e
--- /dev/null
@@ -0,0 +1,4500 @@
+diff -Narup linux-2.4.31-orig/drivers/net/Config.in linux-2.4.31/drivers/net/Config.in
+--- linux-2.4.31-orig/drivers/net/Config.in    2005-01-19 06:09:56.000000000 -0800
++++ linux-2.4.31/drivers/net/Config.in 2005-08-03 09:52:16.000000000 -0700
+@@ -116,6 +116,19 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; the
+       dep_tristate '    SMC Ultra support' CONFIG_ULTRA $CONFIG_ISA
+       dep_tristate '    SMC Ultra32 EISA support' CONFIG_ULTRA32 $CONFIG_EISA
+       dep_tristate '    SMC 9194 support' CONFIG_SMC9194 $CONFIG_ISA
++      tristate '    SMC 91111 support' CONFIG_SMC91111
++      if [ "$CONFIG_SMC91111" != "n" ]; then
++         bool '      Advanced configuration options for SMC91111' CONFIG_SMC91111_ADVANCED
++         if [ "$CONFIG_SMC91111_ADVANCED" = "n" ]; then
++            define_bool CONFIG_SMC91111_BYTE_SWAP n
++            define_bool CONFIG_SMC91111_USE_8_BIT y
++            define_bool CONFIG_SMC91111_USE_32_BIT y
++         else
++            bool '      Byte swap device accesses' CONFIG_SMC91111_BYTE_SWAP
++            bool '      Allow 8 bit device accesses' CONFIG_SMC91111_USE_8_BIT
++            bool '      Allow 32 bit device accesses' CONFIG_SMC91111_USE_32_BIT
++         fi
++      fi
+    fi
+    bool '  Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL
+    if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then
+diff -Narup linux-2.4.31-orig/drivers/net/Makefile linux-2.4.31/drivers/net/Makefile
+--- linux-2.4.31-orig/drivers/net/Makefile     2005-01-19 06:09:56.000000000 -0800
++++ linux-2.4.31/drivers/net/Makefile  2005-08-03 10:17:28.000000000 -0700
+@@ -139,6 +139,7 @@ obj-$(CONFIG_SHAPER) += shaper.o
+ obj-$(CONFIG_SK_G16) += sk_g16.o
+ obj-$(CONFIG_HP100) += hp100.o
+ obj-$(CONFIG_SMC9194) += smc9194.o
++obj-$(CONFIG_SMC91111) += smc91111.o
+ obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
+ obj-$(CONFIG_ARM_ETHERH) += 8390.o
+ obj-$(CONFIG_WD80x3) += wd.o 8390.o
+diff -Narup linux-2.4.31-orig/drivers/net/smc91111.c linux-2.4.31/drivers/net/smc91111.c
+--- linux-2.4.31-orig/drivers/net/smc91111.c   1969-12-31 16:00:00.000000000 -0800
++++ linux-2.4.31/drivers/net/smc91111.c        2005-08-03 09:52:34.000000000 -0700
+@@ -0,0 +1,3746 @@
++/*------------------------------------------------------------------------
++ . smc91111.c
++ . This is a driver for SMSC's 91C111 single-chip Ethernet device.
++ .
++ . Copyright (C) 2001 Standard Microsystems Corporation (SMSC)
++ .       Developed by Simple Network Magic Corporation (SNMC)
++ . Copyright (C) 1996 by Erik Stahlman (ES)
++ .
++ . This program is free software; you can redistribute it and/or modify
++ . it under the terms of the GNU 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
++ .
++ . Information contained in this file was obtained from the LAN91C111
++ . manual from SMC.  To get a copy, if you really want one, you can find
++ . information under www.smsc.com.
++ .
++ .
++ . "Features" of the SMC chip:
++ .   Integrated PHY/MAC for 10/100BaseT Operation
++ .   Supports internal and external MII
++ .   Integrated 8K packet memory
++ .   EEPROM interface for configuration
++ .
++ . Arguments:
++ .    io      = for the base address
++ .    irq     = for the IRQ
++ .    nowait  = 0 for normal wait states, 1 eliminates additional wait states
++ .
++ . author:
++ .    Erik Stahlman                           ( erik@vt.edu )
++ .    Daris A Nevil                           ( dnevil@snmc.com )
++ . contributors:
++ .      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
++ .
++ . Hardware multicast code from Peter Cammaert ( pc@denkart.be )
++ .
++ . Sources:
++ .    o   SMSC LAN91C111 databook (www.smsc.com)
++ .    o   smc9194.c by Erik Stahlman
++ .    o   skeleton.c by Donald Becker ( becker@scyld.com )
++ .
++ . History:
++ .      08/20/00  Arnaldo Melo   fix kfree(skb) in smc_hardware_send_packet
++ .      12/15/00  Christian Jullien fix "Warning: kfree_skb on hard IRQ"
++ .    04/25/01  Daris A Nevil  Initial public release through SMSC
++ .    03/16/01  Daris A Nevil  Modified smc9194.c for use with LAN91C111
++ .    08/22/01  Scott Anderson Merge changes from smc9194 to smc91111
++ ----------------------------------------------------------------------------*/
++
++// Use power-down feature of the chip
++#define POWER_DOWN    1
++
++/*
++ . DEBUGGING LEVELS
++ .
++ . 0 for normal operation
++ . 1 for slightly more details
++ . >2 for various levels of increasingly useless information
++ .    2 for interrupt tracking, status flags
++ .    3 for packet info
++ .    4 for complete packet dumps
++*/
++#ifndef SMC_DEBUG
++#define SMC_DEBUG 0
++#endif
++
++static const char version[] =
++      "smc91111.c:v1.0saa 08/22/01 by Daris A Nevil (dnevil@snmc.com)\n";
++
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/init.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++
++#ifdef CONFIG_SYSCTL
++#include <linux/proc_fs.h>
++#include <linux/sysctl.h>
++#endif
++
++#include "smc91111.h"
++
++#ifdef CONFIG_ISA
++
++/*
++ .the LAN91C111 can be at any of the following port addresses.  To change,
++ .for a slightly different card, you can add it to the array.  Keep in
++ .mind that the array must end in zero.
++*/
++static unsigned int smc_portlist[] __initdata = {
++      0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
++      0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
++};
++
++#endif  /* CONFIG_ISA */
++
++static struct net_device *global_dev = NULL;
++#ifndef SMC91111_BASE_ADDR
++# define SMC91111_BASE_ADDR -1
++#endif
++static int io = SMC91111_BASE_ADDR;
++#ifndef SMC91111_IRQ
++# define SMC91111_IRQ -1
++#endif
++static int irq = SMC91111_IRQ;
++static int nowait = 1;                //Haup=>
++
++MODULE_PARM(io, "i");
++MODULE_PARM(irq, "i");
++MODULE_PARM(nowait, "i");
++MODULE_PARM_DESC(io, "SMC 91111 I/O base address");
++MODULE_PARM_DESC(irq, "SMC 91111 IRQ number");
++
++/*
++ . Wait time for memory to be free.  This probably shouldn't be
++ . tuned that much, as waiting for this means nothing else happens
++ . in the system
++*/
++#define MEMORY_WAIT_TIME 16
++
++#if SMC_DEBUG > 2
++#define PRINTK3(args...) printk(args)
++#else
++#define PRINTK3(args...)
++#endif
++
++#if SMC_DEBUG > 1
++#define PRINTK2(args...) printk(args)
++#else
++#define PRINTK2(args...)
++#endif
++
++#if SMC_DEBUG > 0
++#define PRINTK(args...) printk(args)
++#else
++#define PRINTK(args...)
++#endif
++
++
++/*------------------------------------------------------------------------
++ .
++ . The internal workings of the driver.  If you are changing anything
++ . here with the SMC stuff, you should have the datasheet and know
++ . what you are doing.
++ .
++ -------------------------------------------------------------------------*/
++#define CARDNAME "LAN91C111"
++
++// Memory sizing constant
++#define LAN91C111_MEMORY_MULTIPLIER   (1024*2)
++
++/* store this information for the driver.. */
++struct smc_local {
++
++      // these are things that the kernel wants me to keep, so users
++      // can find out semi-useless statistics of how well the card is
++      // performing
++      struct net_device_stats stats;
++
++      // If I have to wait until memory is available to send
++      // a packet, I will store the skbuff here, until I get the
++      // desired memory.  Then, I'll send it out and free it.
++      struct sk_buff * saved_skb;
++
++      // This keeps track of how many packets that I have
++      // sent out.  When an TX_EMPTY interrupt comes, I know
++      // that all of these have been sent.
++      int     packets_waiting;
++
++      // Set to true during the auto-negotiation sequence
++      int     autoneg_active;
++
++      // Address of our PHY port
++      word    phyaddr;
++
++      // Type of PHY
++      word    phytype;
++
++      // Last contents of PHY Register 18
++      word    lastPhy18;
++
++      // Contains the current active transmission mode
++      word    tcr_cur_mode;
++
++      // Contains the current active receive mode
++      word    rcr_cur_mode;
++
++      // Contains the current active receive/phy mode
++      word    rpc_cur_mode;
++
++
++#ifdef CONFIG_SYSCTL
++
++      // Root directory /proc/sys/dev
++      // Second entry must be null to terminate the table
++      ctl_table root_table[2];
++
++      // Directory for this device /proc/sys/dev/ethX
++      // Again the second entry must be zero to terminate
++      ctl_table eth_table[2];
++
++      // This is the parameters (file) table
++      ctl_table param_table[CTL_SMC_LAST_ENTRY];
++
++      // Saves the sysctl header returned by register_sysctl_table()
++      // we send this to unregister_sysctl_table()
++      struct ctl_table_header *sysctl_header;
++
++      // Parameter variables (files) go here
++      char ctl_info[1024];
++      int ctl_swfdup;
++      int ctl_ephloop;
++      int ctl_miiop;
++      int ctl_autoneg;
++      int ctl_rfduplx;
++      int ctl_rspeed;
++      int ctl_afduplx;
++      int ctl_aspeed;
++      int ctl_lnkfail;
++      int ctl_forcol;
++      int ctl_filtcar;
++      int ctl_freemem;
++      int ctl_totmem;
++      int ctl_leda;
++      int ctl_ledb;
++      int ctl_chiprev;
++#if SMC_DEBUG > 0
++      int ctl_reg_bsr;
++      int ctl_reg_tcr;
++      int ctl_reg_esr;
++      int ctl_reg_rcr;
++      int ctl_reg_ctrr;
++      int ctl_reg_mir;
++      int ctl_reg_rpcr;
++      int ctl_reg_cfgr;
++      int ctl_reg_bar;
++      int ctl_reg_iar0;
++      int ctl_reg_iar1;
++      int ctl_reg_iar2;
++      int ctl_reg_gpr;
++      int ctl_reg_ctlr;
++      int ctl_reg_mcr;
++      int ctl_reg_pnr;
++      int ctl_reg_fpr;
++      int ctl_reg_ptr;
++      int ctl_reg_dr;
++      int ctl_reg_isr;
++      int ctl_reg_mtr1;
++      int ctl_reg_mtr2;
++      int ctl_reg_mtr3;
++      int ctl_reg_mtr4;
++      int ctl_reg_miir;
++      int ctl_reg_revr;
++      int ctl_reg_ercvr;
++      int ctl_reg_extr;
++      int ctl_phy_ctrl;
++      int ctl_phy_stat;
++      int ctl_phy_id1;
++      int ctl_phy_id2;
++      int ctl_phy_adc;
++      int ctl_phy_remc;
++      int ctl_phy_cfg1;
++      int ctl_phy_cfg2;
++      int ctl_phy_int;
++      int ctl_phy_mask;
++#endif // SMC_DEBUG > 0
++
++
++#endif // CONFIG_SYSCTL
++
++};
++
++
++/*-----------------------------------------------------------------
++ .
++ .  The driver can be entered at any of the following entry points.
++ .
++ .------------------------------------------------------------------  */
++
++/*
++ . The kernel calls this function when someone wants to use the device,
++ . typically 'ifconfig ethX up'.
++*/
++static int smc_open(struct net_device *dev);
++
++/*
++ . Our watchdog timed out. Called by the networking layer
++*/
++static void smc_timeout(struct net_device *dev);
++
++/*
++ . This is called by the kernel in response to 'ifconfig ethX down'.  It
++ . is responsible for cleaning up everything that the open routine
++ . does, and maybe putting the card into a powerdown state.
++*/
++static int smc_close(struct net_device *dev);
++
++/*
++ . This routine allows the proc file system to query the driver's
++ . statistics.
++*/
++static struct net_device_stats * smc_query_statistics( struct net_device *dev);
++
++/*
++ . Finally, a call to set promiscuous mode ( for TCPDUMP and related
++ . programs ) and multicast modes.
++*/
++static void smc_set_multicast_list(struct net_device *dev);
++
++/*
++ . CRC compute
++ */
++static int crc32( char * s, int length );
++
++/*
++ . Configures the PHY through the MII Management interface
++*/
++static void smc_phy_configure(struct net_device* dev);
++
++/*---------------------------------------------------------------
++ .
++ . Interrupt level calls..
++ .
++ ----------------------------------------------------------------*/
++
++/*
++ . Handles the actual interrupt
++*/
++static void smc_interrupt(int irq, void *, struct pt_regs *regs);
++/*
++ . This is a separate procedure to handle the receipt of a packet, to
++ . leave the interrupt code looking slightly cleaner
++*/
++inline static void smc_rcv( struct net_device *dev );
++/*
++ . This handles a TX interrupt, which is only called when an error
++ . relating to a packet is sent.
++*/
++inline static void smc_tx( struct net_device * dev );
++
++/*
++ . This handles interrupts generated from PHY register 18
++*/
++static void smc_phy_interrupt(struct net_device* dev);
++
++/*
++ ------------------------------------------------------------
++ .
++ . Internal routines
++ .
++ ------------------------------------------------------------
++*/
++
++/*
++ . Test if a given location contains a chip, trying to cause as
++ . little damage as possible if it's not a SMC chip.
++*/
++static int smc_probe(struct net_device *dev, unsigned long ioaddr);
++
++/*
++ . A rather simple routine to print out a packet for debugging purposes.
++*/
++#if SMC_DEBUG > 2
++static void print_packet( byte *, int );
++#endif
++
++#define tx_done(dev) 1
++
++/* this is called to actually send the packet to the chip */
++static void smc_hardware_send_packet( struct net_device * dev );
++
++/* Since I am not sure if I will have enough room in the chip's ram
++ . to store the packet, I call this routine, which either sends it
++ . now, or generates an interrupt when the card is ready for the
++ . packet */
++static int  smc_wait_to_send_packet( struct sk_buff * skb, struct net_device *dev );
++
++/* this does a soft reset on the device */
++static void smc_reset( struct net_device* dev );
++
++/* Enable Interrupts, Receive, and Transmit */
++static void smc_enable( struct net_device *dev );
++
++/* this puts the device in an inactive state */
++static void smc_shutdown( unsigned long ioaddr );
++
++/* This routine will find the IRQ of the driver if one is not
++ . specified in the input to the device.  */
++static int smc_findirq( unsigned long ioaddr );
++
++/* Routines to Read and Write the PHY Registers across the
++   MII Management Interface
++*/
++
++static word smc_read_phy_register(unsigned long ioaddr,
++                                byte phyaddr, byte phyreg);
++static void smc_write_phy_register(unsigned long ioaddr,
++      byte phyaddr, byte phyreg, word phydata);
++
++/*
++  Initilizes our device's sysctl proc filesystem
++*/
++
++#ifdef CONFIG_SYSCTL
++static void smc_sysctl_register(struct net_device *dev);
++static void smc_sysctl_unregister(struct net_device *dev);
++#endif /* CONFIG_SYSCTL */
++
++/*
++ . Function: smc_reset( struct net_device* dev )
++ . Purpose:
++ .    This sets the SMC91111 chip to its normal state, hopefully from whatever
++ .    mess that any other DOS driver has put it in.
++ .
++ . Maybe I should reset more registers to defaults in here?  SOFTRST  should
++ . do that for me.
++ .
++ . Method:
++ .    1.  send a SOFT RESET
++ .    2.  wait for it to finish
++ .    3.  enable autorelease mode
++ .    4.  reset the memory management unit
++ .    5.  clear all interrupts
++ .
++*/
++static void smc_reset( struct net_device* dev )
++{
++      //struct smc_local *lp  = (struct smc_local *)dev->priv;
++      unsigned long ioaddr = dev->base_addr;
++
++      PRINTK2("%s:smc_reset\n", dev->name);
++
++      /* This resets the registers mostly to defaults, but doesn't
++         affect EEPROM.  That seems unnecessary */
++      SMC_SELECT_BANK( 0 );
++      SMC_SET_RCR( RCR_SOFTRST );
++
++      /* Setup the Configuration Register */
++      /* This is necessary because the CONFIG_REG is not affected */
++      /* by a soft reset */
++
++      SMC_SELECT_BANK( 1 );
++      SMC_SET_CONFIG( CONFIG_DEFAULT );
++
++      /* Setup for fast accesses if requested */
++      /* If the card/system can't handle it then there will */
++      /* be no recovery except for a hard reset or power cycle */
++
++      if (dev->dma)
++              SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_NO_WAIT );
++
++#ifdef POWER_DOWN
++      /* Release from possible power-down state */
++      /* Configuration register is not affected by Soft Reset */
++      SMC_SELECT_BANK( 1 );
++      SMC_SET_CONFIG( SMC_GET_CONFIG() | CONFIG_EPH_POWER_EN );
++#endif
++
++      SMC_SELECT_BANK( 0 );
++
++      /* this should pause enough for the chip to be happy */
++      mdelay(10);
++
++      /* Disable transmit and receive functionality */
++      SMC_SET_RCR( RCR_CLEAR );
++      SMC_SET_TCR( TCR_CLEAR );
++
++      /* set the control register to automatically
++         release successfully transmitted packets, to make the best
++         use out of our limited memory */
++      SMC_SELECT_BANK( 1 );
++      SMC_SET_CTL( SMC_GET_CTL() | CTL_AUTO_RELEASE );
++
++      /* Reset the MMU */
++      SMC_SELECT_BANK( 2 );
++      SMC_SET_MMU_CMD( MC_RESET );
++
++      /* Note:  It doesn't seem that waiting for the MMU busy is needed here,
++         but this is a place where future chipsets _COULD_ break.  Be wary
++         of issuing another MMU command right after this */
++
++      /* Disable all interrupts */
++      SMC_SET_INT_MASK( 0 );
++}
++
++/*
++ . Function: smc_enable
++ . Purpose: let the chip talk to the outside work
++ . Method:
++ .    1.  Enable the transmitter
++ .    2.  Enable the receiver
++ .    3.  Enable interrupts
++*/
++static void smc_enable( struct net_device *dev )
++{
++      unsigned long ioaddr    = dev->base_addr;
++      struct smc_local *lp    = (struct smc_local *)dev->priv;
++
++      PRINTK2("%s:smc_enable\n", dev->name);
++
++      SMC_SELECT_BANK( 0 );
++      /* see the header file for options in TCR/RCR DEFAULT*/
++      SMC_SET_TCR( lp->tcr_cur_mode );
++      SMC_SET_RCR( lp->rcr_cur_mode );
++
++      /* now, enable interrupts */
++      SMC_SELECT_BANK( 2 );
++      SMC_SET_INT_MASK( SMC_INTERRUPT_MASK );
++}
++
++/*
++ . Function: smc_shutdown
++ . Purpose:  closes down the SMC91xxx chip.
++ . Method:
++ .    1. zero the interrupt mask
++ .    2. clear the enable receive flag
++ .    3. clear the enable xmit flags
++ .
++ . TODO:
++ .   (1) maybe utilize power down mode.
++ .    Why not yet?  Because while the chip will go into power down mode,
++ .    the manual says that it will wake up in response to any I/O requests
++ .    in the register space.   Empirical results do not show this working.
++*/
++static void smc_shutdown( unsigned long ioaddr )
++{
++      PRINTK2(CARDNAME ":smc_shutdown\n");
++
++      /* no more interrupts for me */
++      SMC_SELECT_BANK( 2 );
++      SMC_SET_INT_MASK( 0 );
++
++      /* and tell the card to stay away from that nasty outside world */
++      SMC_SELECT_BANK( 0 );
++      SMC_SET_RCR( RCR_CLEAR );
++      SMC_SET_TCR( TCR_CLEAR );
++
++#ifdef POWER_DOWN
++      /* finally, shut the chip down */
++      SMC_SELECT_BANK( 1 );
++      SMC_SET_CONFIG( SMC_GET_CONFIG() & ~CONFIG_EPH_POWER_EN );
++#endif
++}
++
++
++/*
++ . Function: smc_setmulticast( int ioaddr, int count, dev_mc_list * adds )
++ . Purpose:
++ .    This sets the internal hardware table to filter out unwanted multicast
++ .    packets before they take up memory.
++ .
++ .    The SMC chip uses a hash table where the high 6 bits of the CRC of
++ .    address are the offset into the table.  If that bit is 1, then the
++ .    multicast packet is accepted.  Otherwise, it's dropped silently.
++ .
++ .    To use the 6 bits as an offset into the table, the high 3 bits are the
++ .    number of the 8 bit register, while the low 3 bits are the bit within
++ .    that register.
++ .
++ . This routine is based very heavily on the one provided by Peter Cammaert.
++*/
++
++
++static void smc_setmulticast( unsigned long ioaddr, int count,
++                            struct dev_mc_list * addrs ) {
++      int                     i;
++      unsigned char           multicast_table[ 8 ];
++      struct dev_mc_list      * cur_addr;
++      /* table for flipping the order of 3 bits */
++      unsigned char invert3[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
++
++      PRINTK2(CARDNAME ":smc_setmulticast\n");
++
++      /* start with a table of all zeros: reject all */
++      memset( multicast_table, 0, sizeof( multicast_table ) );
++
++      cur_addr = addrs;
++      for ( i = 0; i < count ; i ++, cur_addr = cur_addr->next  ) {
++              int position;
++
++              /* do we have a pointer here? */
++              if ( !cur_addr )
++                      break;
++              /* make sure this is a multicast address - shouldn't this
++                 be a given if we have it here ? */
++              if ( !( *cur_addr->dmi_addr & 1 ) )
++                      continue;
++
++              /* only use the low order bits */
++              position = crc32( cur_addr->dmi_addr, 6 ) & 0x3f;
++
++              /* do some messy swapping to put the bit in the right spot */
++              multicast_table[invert3[position&7]] |=
++                                      (1<<invert3[(position>>3)&7]);
++
++      }
++      /* now, the table can be loaded into the chipset */
++      SMC_SELECT_BANK( 3 );
++      SMC_SET_MCAST( multicast_table );
++}
++
++/*
++  Finds the CRC32 of a set of bytes.
++  Again, from Peter Cammaert's code.
++*/
++static int crc32( char * s, int length ) {
++      /* indices */
++      int perByte;
++      int perBit;
++      /* crc polynomial for Ethernet */
++      const unsigned long poly = 0xedb88320;
++      /* crc value - preinitialized to all 1's */
++      unsigned long crc_value = 0xffffffff;
++
++      for ( perByte = 0; perByte < length; perByte ++ ) {
++              unsigned char   c;
++
++              c = *(s++);
++              for ( perBit = 0; perBit < 8; perBit++ ) {
++                      crc_value = (crc_value>>1)^
++                              (((crc_value^c)&0x01)?poly:0);
++                      c >>= 1;
++              }
++      }
++      return  crc_value;
++}
++
++
++/*
++ . Function: smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * )
++ . Purpose:
++ .    Attempt to allocate memory for a packet, if chip-memory is not
++ .    available, then tell the card to generate an interrupt when it
++ .    is available.
++ .
++ . Algorithm:
++ .
++ . o  if the saved_skb is not currently null, then drop this packet
++ .    on the floor.  This should never happen, because of TBUSY.
++ . o  if the saved_skb is null, then replace it with the current packet,
++ . o  See if I can sending it now.
++ . o  (NO): Enable interrupts and let the interrupt handler deal with it.
++ . o  (YES):Send it now.
++*/
++static int smc_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
++{
++      struct smc_local *lp    = (struct smc_local *)dev->priv;
++      unsigned long ioaddr    = dev->base_addr;
++      word                    length;
++      unsigned short          numPages;
++      word                    time_out;
++      word                    status;
++
++      PRINTK3("%s:smc_wait_to_send_packet\n", dev->name);
++
++      netif_stop_queue(dev);
++      /* Well, I want to send the packet.. but I don't know
++         if I can send it right now...  */
++
++      if ( lp->saved_skb) {
++              /* THIS SHOULD NEVER HAPPEN. */
++              lp->stats.tx_aborted_errors++;
++              printk("%s: Bad Craziness - sent packet while busy.\n",
++                      dev->name);
++              return 1;
++      }
++      lp->saved_skb = skb;
++
++      length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
++
++
++      /*
++      ** The MMU wants the number of pages to be the number of 256 bytes
++      ** 'pages', minus 1 ( since a packet can't ever have 0 pages :) )
++      **
++      ** The 91C111 ignores the size bits, but the code is left intact
++      ** for backwards and future compatibility.
++      **
++      ** Pkt size for allocating is data length +6 (for additional status
++      ** words, length and ctl!)
++      **
++      ** If odd size then last byte is included in this header.
++      */
++      numPages =   ((length & 0xfffe) + 6);
++      numPages >>= 8; // Divide by 256
++
++      if (numPages > 7 ) {
++              printk("%s: Far too big packet error. \n", dev->name);
++              /* freeing the packet is a good thing here... but should
++               . any packets of this size get down here?   */
++              dev_kfree_skb (skb);
++              lp->saved_skb = NULL;
++              /* this IS an error, but, i don't want the skb saved */
++              netif_wake_queue(dev);
++              return 0;
++      }
++      /* either way, a packet is waiting now */
++      lp->packets_waiting++;
++
++      /* now, try to allocate the memory */
++      SMC_SELECT_BANK( 2 );
++      SMC_SET_MMU_CMD( MC_ALLOC | numPages );
++      /*
++      . Performance Hack
++      .
++      . wait a short amount of time.. if I can send a packet now, I send
++      . it now.  Otherwise, I enable an interrupt and wait for one to be
++      . available.
++      .
++      . I could have handled this a slightly different way, by checking to
++      . see if any memory was available in the FREE MEMORY register.  However,
++      . either way, I need to generate an allocation, and the allocation works
++      . no matter what, so I saw no point in checking free memory.
++      */
++      time_out = MEMORY_WAIT_TIME;
++      do {
++              status = SMC_GET_INT();
++              if ( status & IM_ALLOC_INT ) {
++                      /* acknowledge the interrupt */
++                      SMC_ACK_INT( IM_ALLOC_INT );
++                      break;
++              }
++      } while ( -- time_out );
++
++      if ( !time_out ) {
++              /* oh well, wait until the chip finds memory later */
++              SMC_ENABLE_INT( IM_ALLOC_INT );
++
++              /* Check the status bit one more time just in case */
++              /* it snuk in between the time we last checked it */
++              /* and when we set the interrupt bit */
++              status = SMC_GET_INT();
++              if ( !(status & IM_ALLOC_INT) ) {
++                              PRINTK2("%s: memory allocation deferred. \n",
++                              dev->name);
++                      /* it's deferred, but I'll handle it later */
++                              return 0;
++                      }
++
++              /* Looks like it did sneak in, so disable */
++              /* the interrupt */
++              SMC_DISABLE_INT( IM_ALLOC_INT );
++      }
++      /* or YES! I can send the packet now.. */
++      smc_hardware_send_packet(dev);
++      netif_wake_queue(dev);
++      return 0;
++}
++
++/*
++ . Function:  smc_hardware_send_packet(struct net_device * )
++ . Purpose:
++ .    This sends the actual packet to the SMC9xxx chip.
++ .
++ . Algorithm:
++ .    First, see if a saved_skb is available.
++ .            ( this should NOT be called if there is no 'saved_skb'
++ .    Now, find the packet number that the chip allocated
++ .    Point the data pointers at it in memory
++ .    Set the length word in the chip's memory
++ .    Dump the packet to chip memory
++ .    Check if a last byte is needed ( odd length packet )
++ .            if so, set the control flag right
++ .    Tell the card to send it
++ .    Enable the transmit interrupt, so I know if it failed
++ .    Free the kernel data if I actually sent it.
++*/
++static void smc_hardware_send_packet( struct net_device * dev )
++{
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++      byte                    packet_no;
++      struct sk_buff *        skb = lp->saved_skb;
++      word                    length;
++      unsigned long           ioaddr;
++      byte                    * buf;
++
++      PRINTK3("%s:smc_hardware_send_packet\n", dev->name);
++
++      ioaddr = dev->base_addr;
++
++      if ( !skb ) {
++              PRINTK("%s: In XMIT with no packet to send \n", dev->name);
++              return;
++      }
++      length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
++      buf = skb->data;
++
++      /* If I get here, I _know_ there is a packet slot waiting for me */
++      packet_no = SMC_GET_AR();
++      if ( packet_no & AR_FAILED ) {
++              /* or isn't there?  BAD CHIP! */
++              printk(KERN_DEBUG "%s: Memory allocation failed. \n",
++                      dev->name);
++              dev_kfree_skb_any(skb);
++              lp->saved_skb = NULL;
++              netif_wake_queue(dev);
++              return;
++      }
++
++      /* we have a packet address, so tell the card to use it */
++      SMC_SET_PN( packet_no );
++
++      /* point to the beginning of the packet */
++      SMC_SET_PTR( PTR_AUTOINC );
++
++      PRINTK3("%s: Trying to xmit packet of length %x\n",
++              dev->name, length);
++
++#if SMC_DEBUG > 2
++      printk("Transmitting Packet\n");
++      print_packet( buf, length );
++#endif
++
++      /* send the packet length ( +6 for status, length and ctl byte )
++         and the status word ( set to zeros ) */
++#ifdef CONFIG_SMC91111_USE_32_BIT
++      SMC_outl(  (length +6 ) << 16 , ioaddr + DATA_REG );
++#else
++      SMC_outw( 0, ioaddr + DATA_REG );
++      /* send the packet length ( +6 for status words, length, and ctl*/
++      SMC_outw( (length+6), ioaddr + DATA_REG );
++#endif
++
++      /* send the actual data
++       . I _think_ it's faster to send the longs first, and then
++       . mop up by sending the last word.  It depends heavily
++       . on alignment, at least on the 486.  Maybe it would be
++       . a good idea to check which is optimal?  But that could take
++       . almost as much time as is saved?
++      */
++#ifdef CONFIG_SMC91111_USE_32_BIT
++      SMC_outsl(ioaddr + DATA_REG, buf,  length >> 2 );
++      if ( length & 0x2  )
++              SMC_outw(*((word *)(buf + (length & 0xFFFFFFFC))),ioaddr +
++                              DATA_REG);
++#else
++      SMC_outsw(ioaddr + DATA_REG , buf, (length ) >> 1);
++#endif // CONFIG_SMC91111_USE_32_BIT
++
++      /* Send the last byte, if there is one.   */
++      if ( (length & 1) == 0 ) {
++              SMC_outw( 0, ioaddr + DATA_REG );
++      } else {
++              SMC_outw( 0x2000 | buf[length -1 ], ioaddr + DATA_REG );
++      }
++
++      /* enable the interrupts */
++      SMC_ENABLE_INT( (IM_TX_INT | IM_TX_EMPTY_INT) );
++
++      /* and let the chipset deal with it */
++      SMC_SET_MMU_CMD( MC_ENQUEUE );
++
++      PRINTK2("%s: Sent packet of length %d \n", dev->name, length);
++
++      lp->saved_skb = NULL;
++      dev_kfree_skb_any (skb);
++
++      dev->trans_start = jiffies;
++
++      /* we can send another packet */
++      netif_wake_queue(dev);
++
++      return;
++}
++
++/*-------------------------------------------------------------------------
++ |
++ | smc_init( void )
++ |   Input parameters:
++ |    dev->base_addr == 0, try to find all possible locations
++ |    dev->base_addr > 0x1ff, this is the address to check
++ |    dev->base_addr == <anything else>, return failure code
++ |
++ |   Output:
++ |    0 --> there is a device
++ |    anything else, error
++ |
++ ---------------------------------------------------------------------------
++*/
++static int __init smc_init( void )
++{
++      int rtn;
++
++      PRINTK2(CARDNAME ":smc_init\n");
++
++      /* 
++       * Haup=> Set BRCR1 TWT to wait for 7+1=8 SYS_CLK(63MHz) => 126.98ns > 100 ns)
++       * Changes: 02/09/2004=> reduce Bus Hold Time to 1 SYS_CLK
++       */
++      {
++      #define BRCR_REGMEM_BASE 0x70
++      #define REG_BRCRH0      (BRCR_REGMEM_BASE + 0)
++      #define REG_BRCRH1      (BRCR_REGMEM_BASE + 1)
++      #define REG_BRCRH2      (BRCR_REGMEM_BASE + 2)
++      #define REG_BRCRH3      (BRCR_REGMEM_BASE + 3)
++
++      #define REG_BRCR0       (BRCR_REGMEM_BASE + 0x10)
++      #define REG_BRCR1       (BRCR_REGMEM_BASE + 0x11)
++      #define REG_BRCR2       (BRCR_REGMEM_BASE + 0x12)
++      #define REG_BRCR3       (BRCR_REGMEM_BASE + 0x13)
++      #define REG_BIUCR       (BRCR_REGMEM_BASE + 0x2A)
++
++      #define __to_asm_token(s)   #s
++
++      #define MF_DCR(rn) __mfdcr_or_dflt(rn, 0)
++
++      #define __mfdcr_or_dflt(rn,default_rval) \
++              ({unsigned int rval;                                            \
++              if (rn == 0)                                                    \
++                      rval = default_rval;                                    \
++              else                                                            \
++                      asm volatile("mfdcr %0," __to_asm_token(rn) : "=r" (rval));  \
++                      rval;})
++
++      #define MT_DCR(rn, v)  \
++              {if (rn != 0) \
++                      asm volatile("mtdcr " __to_asm_token(rn) ",%0" : : "r" (v));}
++
++
++      unsigned int brcr1;
++
++      brcr1 = MF_DCR(REG_BRCR1);
++      printk("smsc91111 org brcr1 = 0x%08x\n", brcr1);
++
++      /* set TWT = 7+1 SYS_CLK */
++      brcr1 = (brcr1 & ~(0x3f<<8)) | (7<<8);
++      /* set TH = 1 SYS_CLK */
++      brcr1 = (brcr1 & ~(0x07<<1)) | (0x01<<1);
++      
++      MT_DCR(REG_BRCR1, brcr1);
++      brcr1 = MF_DCR(REG_BRCR1);
++      printk("smsc91111 (brcr1 = 0x%08x) => TWT cycle = %d\n",
++              brcr1,
++              ((brcr1 & (0x3f<<8))>>8));
++      }       //end of haup
++
++#ifdef MODULE
++      if (io == -1)
++              printk(KERN_WARNING
++              CARDNAME": You shouldn't use auto-probing with insmod!\n" );
++#endif
++
++      if (global_dev) {
++              printk(CARDNAME ": already initialized.\n");
++              return -EBUSY;
++      }
++
++      global_dev = init_etherdev(0, sizeof(struct smc_local));
++      if (!global_dev) {
++              printk(CARDNAME ": could not allocate device.\n");
++              return -ENODEV;
++      }
++      SET_MODULE_OWNER(global_dev);
++
++      /* copy the parameters from insmod into the device structure */
++      if (io != -1)
++              global_dev->base_addr   = io;
++      if (irq != -1)
++              global_dev->irq = irq;
++      global_dev->dma         = nowait; // Use DMA field for nowait
++
++#ifdef CONFIG_ISA
++      /*  try a specific location */
++      if (global_dev->base_addr > 0x1ff)
++              rtn = smc_probe(global_dev, global_dev->base_addr);
++      else if (global_dev->base_addr != 0)
++              rtn = -ENXIO;
++      else {
++              int i;
++
++              /* check every ethernet address */
++              for (i = 0; smc_portlist[i]; i++) {
++                      rtn = smc_probe(global_dev, smc_portlist[i]);
++                      if (rtn == 0)
++                              break;
++              }
++      }
++
++xxxx
++#else
++      if (global_dev->base_addr == -1) {
++              printk(KERN_WARNING
++              CARDNAME": SMC91111_BASE_ADDR not set!\n" );
++              rtn = -ENXIO;
++      }
++      else
++              rtn = smc_probe(global_dev,
++                              (int)ioremap(global_dev->base_addr,
++                                           SMC_IO_EXTENT));
++#endif
++
++      if (rtn != 0) {
++              printk(CARDNAME ": not found.\n");
++              /* couldn't find anything */
++#ifndef CONFIG_ISA
++              iounmap((void *)global_dev->base_addr);
++#endif
++              kfree(global_dev->priv);
++              unregister_netdev(global_dev);
++              kfree(global_dev);
++      }
++
++      return rtn;
++}
++
++/*----------------------------------------------------------------------
++ . smc_findirq
++ .
++ . This routine has a simple purpose -- make the SMC chip generate an
++ . interrupt, so an auto-detect routine can detect it, and find the IRQ,
++ ------------------------------------------------------------------------
++*/
++int __init smc_findirq( unsigned long ioaddr )
++{
++      int     timeout = 20;
++      unsigned long cookie;
++
++      PRINTK2(CARDNAME ":smc_findirq\n");
++
++      /* I have to do a STI() here, because this is called from
++         a routine that does an CLI during this process, making it
++         rather difficult to get interrupts for auto detection */
++      sti();
++
++      cookie = probe_irq_on();
++
++      /*
++       * What I try to do here is trigger an ALLOC_INT. This is done
++       * by allocating a small chunk of memory, which will give an interrupt
++       * when done.
++       */
++
++
++      SMC_SELECT_BANK(2);
++      /* enable ALLOCation interrupts ONLY */
++      SMC_SET_INT_MASK( IM_ALLOC_INT );
++
++      /*
++       . Allocate 512 bytes of memory.  Note that the chip was just
++       . reset so all the memory is available
++      */
++      SMC_SET_MMU_CMD( MC_ALLOC | 1 );
++
++      /*
++       . Wait until positive that the interrupt has been generated
++      */
++      while ( timeout ) {
++              byte    int_status;
++
++              int_status = SMC_GET_INT();
++
++              if ( int_status & IM_ALLOC_INT )
++                      break;          /* got the interrupt */
++              timeout--;
++      }
++
++      /* there is really nothing that I can do here if timeout fails,
++         as autoirq_report will return a 0 anyway, which is what I
++         want in this case.   Plus, the clean up is needed in both
++         cases.  */
++
++      /* DELAY HERE!
++         On a fast machine, the status might change before the interrupt
++         is given to the processor.  This means that the interrupt was
++         never detected, and autoirq_report fails to report anything.
++         This should fix autoirq_* problems.
++      */
++      mdelay(10);
++
++      /* and disable all interrupts again */
++      SMC_SET_INT_MASK( 0 );
++
++      /* clear hardware interrupts again, because that's how it
++         was when I was called... */
++      cli();
++
++      /* and return what I found */
++      return probe_irq_off(cookie);
++}
++
++/*----------------------------------------------------------------------
++ . Function: smc_probe( unsigned long ioaddr )
++ .
++ . Purpose:
++ .    Tests to see if a given ioaddr points to an SMC91111 chip.
++ .    Returns a 0 on success
++ .
++ . Algorithm:
++ .    (1) see if the high byte of BANK_SELECT is 0x33
++ .    (2) compare the ioaddr with the base register's address
++ .    (3) see if I recognize the chip ID in the appropriate register
++ .
++ .---------------------------------------------------------------------
++ */
++/*---------------------------------------------------------------
++ . Here I do typical initialization tasks.
++ .
++ . o  Initialize the structure if needed
++ . o  print out my vanity message if not done so already
++ . o  print out what type of hardware is detected
++ . o  print out the ethernet address
++ . o  find the IRQ
++ . o  set up my private data
++ . o  configure the dev structure with my subroutines
++ . o  actually GRAB the irq.
++ . o  GRAB the region
++ .-----------------------------------------------------------------
++*/
++static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
++{
++      int i, memory, retval;
++      static unsigned version_printed;
++      unsigned int    bank;
++
++      const char *version_string;
++      const char *if_string = 0;
++
++      /* registers */
++      word    revision_register;
++      word  base_address_register;
++      word memory_info_register;
++
++      PRINTK2(CARDNAME ":smc_probe\n");
++
++      /* Grab the region so that no one else tries to probe our ioports. */
++      if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name))
++              return -EBUSY;
++
++      /* First, see if the high byte is 0x33 */
++      bank = SMC_CURRENT_BANK();
++      if ( (bank & 0xFF00) != 0x3300 ) {
++              if ( (bank & 0xFF) == 0x33 ) {
++                      printk(CARDNAME
++                             ": Detected possible byte-swapped interface"
++                             " at IOADDR %lx\n", ioaddr);
++              }
++              retval = -ENODEV;
++              goto err_out;
++      }
++      /* The above MIGHT indicate a device, but I need to write to further
++              test this.  */
++      SMC_SELECT_BANK(0);
++      bank = SMC_CURRENT_BANK();
++      if ( (bank & 0xFF00 ) != 0x3300 ) {
++              retval = -ENODEV;
++              goto err_out;
++      }
++      /* well, we've already written once, so hopefully another time won't
++         hurt.  This time, I need to switch the bank register to bank 1,
++         so I can access the base address register */
++      SMC_SELECT_BANK(1);
++      base_address_register = SMC_GET_BASE();
++      base_address_register = ((base_address_register & 0xE000)
++                               | ((base_address_register & 0x1F00) >> 3));
++      if ( (ioaddr & (PAGE_SIZE-1)) != base_address_register )  {
++              printk(CARDNAME ": IOADDR %lx doesn't match configuration (%x)."
++                      "Probably not a SMC chip\n",
++                      ioaddr, base_address_register );
++              /* well, the base address register didn't match.  Must not have
++                 been a SMC chip after all. */
++              retval = -ENODEV;
++              goto err_out;
++      }
++
++      /*  check if the revision register is something that I recognize.
++          These might need to be added to later, as future revisions
++          could be added.  */
++      SMC_SELECT_BANK(3);
++      revision_register  = SMC_GET_REV();
++      if ( !chip_ids[ ( revision_register  >> 4 ) & 0xF  ] ) {
++              /* I don't recognize this chip, so... */
++              printk(CARDNAME ": IO %lx: Unrecognized revision register:"
++                      " %x, Contact author. \n",
++                      ioaddr, revision_register );
++
++              retval = -ENODEV;
++              goto err_out;
++      }
++
++      /* at this point I'll assume that the chip is an SMC9xxx.
++         It might be prudent to check a listing of MAC addresses
++         against the hardware address, or do some other tests. */
++
++      if (version_printed++ == 0)
++              printk("%s", version);
++
++      /* fill in some of the fields */
++      dev->base_addr = ioaddr;
++
++      /*
++       . Get the MAC address ( bank 1, regs 4 - 9 )
++      */
++      SMC_SELECT_BANK( 1 );
++      for ( i = 0; i < 6; i += 2 ) {
++              word    address;
++
++              address = SMC_inw( ioaddr + ADDR0_REG + i  );
++              dev->dev_addr[ i + 1] = address >> 8;
++              dev->dev_addr[ i ] = address & 0xFF;
++      }
++
++      /* get the memory information */
++
++      SMC_SELECT_BANK( 0 );
++      memory_info_register = SMC_GET_MIR();
++      memory = memory_info_register & (word)0x00ff;
++      memory *= LAN91C111_MEMORY_MULTIPLIER;
++
++      /*
++       Now, I want to find out more about the chip.  This is sort of
++       redundant, but it's cleaner to have it in both, rather than having
++       one VERY long probe procedure.
++      */
++      SMC_SELECT_BANK(3);
++      revision_register  = SMC_GET_REV();
++      version_string = chip_ids[ ( revision_register  >> 4 ) & 0xF  ];
++      if ( !version_string ) {
++              /* I shouldn't get here because this call was done before.... */
++              retval = -ENODEV;
++              goto err_out;
++      }
++
++
++      /* now, reset the chip, and put it into a known state */
++      smc_reset( dev );
++
++      /*
++       . If dev->irq is 0, then the device has to be banged on to see
++       . what the IRQ is.
++       .
++       . This banging doesn't always detect the IRQ, for unknown reasons.
++       . a workaround is to reset the chip and try again.
++       .
++       . Interestingly, the DOS packet driver *SETS* the IRQ on the card to
++       . be what is requested on the command line.   I don't do that, mostly
++       . because the card that I have uses a non-standard method of accessing
++       . the IRQs, and because this _should_ work in most configurations.
++       .
++       . Specifying an IRQ is done with the assumption that the user knows
++       . what (s)he is doing.  No checking is done!!!!
++       .
++      */
++      if ( dev->irq < 2 ) {
++              int     trials;
++
++              trials = 3;
++              while ( trials-- ) {
++                      dev->irq = smc_findirq( ioaddr );
++                      if ( dev->irq )
++                              break;
++                      /* kick the card and try again */
++                      smc_reset( dev );
++              }
++      }
++      if (dev->irq == 0 ) {
++              printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
++                      dev->name);
++              retval = -ENODEV;
++              goto err_out;
++      }
++      if (dev->irq == 2) {
++              /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
++               * or don't know which one to set.
++               */
++              dev->irq = 9;
++      }
++
++      /* now, print out the card info, in a short format.. */
++
++      printk("%s: %s(r:%d) at %#lx IRQ:%d\n", dev->name,
++             version_string, revision_register & 0xF, ioaddr, dev->irq );
++      printk(" INTF:%s MEM:%db NOWAIT:%d", if_string, memory, dev->dma );
++      /*
++       . Print the Ethernet address
++      */
++      printk("  ADDR ");
++      for (i = 0; i < 5; i++)
++              printk("%2.2x:", dev->dev_addr[i] );
++      printk("%2.2x \n", dev->dev_addr[5] );
++
++      /* set the private data to zero by default */
++      memset(dev->priv, 0, sizeof(struct smc_local));
++
++      /* Fill in the fields of the device structure with ethernet values. */
++      ether_setup(dev);
++
++      /* Grab the IRQ */
++              retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev);
++              if (retval) {
++              goto err_out;
++              }
++
++      dev->open                       = smc_open;
++      dev->stop                       = smc_close;
++      dev->hard_start_xmit            = smc_wait_to_send_packet;
++      dev->tx_timeout                 = smc_timeout;
++      dev->watchdog_timeo             = HZ/20;
++      dev->get_stats                  = smc_query_statistics;
++      dev->set_multicast_list         = smc_set_multicast_list;
++
++      return 0;
++
++err_out:
++      release_region(ioaddr, SMC_IO_EXTENT);
++      return retval;
++}
++
++#if SMC_DEBUG > 2
++static void print_packet( byte * buf, int length )
++{
++#if 1
++#if SMC_DEBUG > 3
++      int i;
++      int remainder;
++      int lines;
++#endif
++
++      printk("Packet of length %d \n", length );
++
++#if SMC_DEBUG > 3
++      lines = length / 16;
++      remainder = length % 16;
++
++      for ( i = 0; i < lines ; i ++ ) {
++              int cur;
++
++              for ( cur = 0; cur < 8; cur ++ ) {
++                      byte a, b;
++
++                      a = *(buf ++ );
++                      b = *(buf ++ );
++                      printk("%02x%02x ", a, b );
++              }
++              printk("\n");
++      }
++      for ( i = 0; i < remainder/2 ; i++ ) {
++              byte a, b;
++
++              a = *(buf ++ );
++              b = *(buf ++ );
++              printk("%02x%02x ", a, b );
++      }
++      printk("\n");
++#endif
++#endif
++}
++#endif
++
++
++/*
++ * Open and Initialize the board
++ *
++ * Set up everything, reset the card, etc ..
++ *
++ */
++static int smc_open(struct net_device *dev)
++{
++      struct smc_local *lp    = (struct smc_local *)dev->priv;
++      unsigned long ioaddr    = dev->base_addr;
++      int     i;      /* used to set hw ethernet address */
++
++      PRINTK2("%s:smc_open\n", dev->name);
++
++      /* clear out all the junk that was put here before... */
++      memset(dev->priv, 0, sizeof(struct smc_local));
++
++      // Setup the default Register Modes
++      lp->tcr_cur_mode = TCR_DEFAULT;
++      lp->rcr_cur_mode = RCR_DEFAULT;
++      lp->rpc_cur_mode = RPC_DEFAULT;
++
++      // Set default parameters (files)
++      lp->ctl_swfdup = 0;
++      lp->ctl_ephloop = 0;
++      lp->ctl_miiop = 0;
++      lp->ctl_autoneg = 1;    //1
++      lp->ctl_rfduplx = 0;    //Haup=> negotiate for HALF?
++      lp->ctl_rspeed = 100;   //100
++      lp->ctl_afduplx = 0;    //1
++      lp->ctl_aspeed = 100;   //100
++      lp->ctl_lnkfail = 1;
++      lp->ctl_forcol = 0;
++      lp->ctl_filtcar = 0;
++
++      /* reset the hardware */
++
++      smc_reset( dev );
++      smc_enable( dev );
++
++      /* Configure the PHY */
++      smc_phy_configure(dev);
++
++      /*
++              According to Becker, I have to set the hardware address
++              at this point, because the (l)user can set it with an
++              ioctl.  Easily done...
++      */
++      SMC_SELECT_BANK( 1 );
++      for ( i = 0; i < 6; i += 2 ) {
++              word    address;
++
++              address = dev->dev_addr[ i + 1 ] << 8 ;
++              address  |= dev->dev_addr[ i ];
++              SMC_outw( address, ioaddr + ADDR0_REG + i );
++      }
++
++#ifdef CONFIG_SYSCTL
++      smc_sysctl_register(dev);
++#endif /* CONFIG_SYSCTL */
++
++      netif_start_queue(dev);
++      return 0;
++}
++
++/*--------------------------------------------------------
++ . Called by the kernel to send a packet out into the void
++ . of the net.  This routine is largely based on
++ . skeleton.c, from Becker.
++ .--------------------------------------------------------
++*/
++static void smc_timeout(struct net_device *dev)
++{
++      struct smc_local *lp    = (struct smc_local *)dev->priv;
++
++      PRINTK3("%s:smc_timeout\n", dev->name);
++
++      /* If we get here, some higher level has decided we are broken.
++         There should really be a "kick me" function call instead. */
++      printk(KERN_WARNING "%s: transmit timed out, %s?\n",
++              dev->name, tx_done(dev) ? "IRQ conflict" :
++              "network cable problem");
++      /* "kick" the adaptor */
++      smc_reset( dev );
++      smc_enable( dev );
++
++#if 0
++      /* Reconfiguring the PHY doesn't seem like a bad idea here, but
++       * it introduced a problem.  Now that this is a timeout routine,
++       * we are getting called from within an interrupt context.
++       * smc_phy_configure() calls smc_wait_ms() which calls
++       * schedule_timeout() which calls schedule().  When schedule()
++       * is called from an interrupt context, it prints out
++       * "Scheduling in interrupt" and then calls BUG().  This is
++       * obviously not desirable.  This was worked around by removing
++       * the call to smc_phy_configure() here because it didn't seem
++       * absolutely necessary.  Ultimately, if smc_wait_ms() is
++       * supposed to be usable from an interrupt context (which it
++       * looks like it thinks it should handle), it should be fixed.
++       */
++      /* Reconfigure the PHY */
++      smc_phy_configure(dev);
++#endif
++      dev->trans_start = jiffies;
++      /* clear anything saved */
++      if (lp->saved_skb != NULL) {
++              dev_kfree_skb (lp->saved_skb);
++              lp->saved_skb = NULL;
++      }
++      ((struct smc_local *)dev->priv)->saved_skb = NULL;
++      netif_wake_queue(dev);
++}
++
++/*--------------------------------------------------------------------
++ .
++ . This is the main routine of the driver, to handle the device when
++ . it needs some attention.
++ .
++ . So:
++ .   first, save state of the chipset
++ .   branch off into routines to handle each case, and acknowledge
++ .        each to the interrupt register
++ .   and finally restore state.
++ .
++ ---------------------------------------------------------------------*/
++static void smc_interrupt(int irq, void * dev_id,  struct pt_regs * regs)
++{
++      struct net_device *dev  = dev_id;
++      unsigned long ioaddr    = dev->base_addr;
++      struct smc_local *lp    = (struct smc_local *)dev->priv;
++
++      byte    status;
++      word    card_stats;
++      byte    mask;
++      int     timeout;
++      /* state registers */
++      word    saved_bank;
++      word    saved_pointer;
++
++      PRINTK3("%s: SMC interrupt started \n", dev->name);
++
++      if (dev == NULL) {
++              printk(KERN_WARNING "%s: irq %d for unknown device.\n",
++                      dev->name, irq);
++              return;
++      }
++
++      saved_bank = SMC_CURRENT_BANK();
++
++      SMC_SELECT_BANK(2);
++      saved_pointer = SMC_GET_PTR();
++
++      /* read the interrupt mask register */
++      mask = SMC_GET_INT_MASK();
++
++      /* disable all interrupts */
++      SMC_SET_INT_MASK( 0 );
++
++      /* set a timeout value, so I don't stay here forever */
++      timeout = 4;
++
++      PRINTK2(KERN_WARNING "%s: MASK IS %x \n", dev->name, mask);
++      do {
++              /* read the status flag, and mask it */
++              status = SMC_GET_INT() & mask;
++              if (!status )
++                      break;
++
++              PRINTK3(KERN_WARNING "%s: Handling interrupt status %x \n",
++                      dev->name, status);
++
++              if (status & IM_RCV_INT) {
++                      /* Got a packet(s). */
++                      PRINTK2(KERN_WARNING
++                              "%s: Receive Interrupt\n", dev->name);
++                      smc_rcv(dev);
++              } else if (status & IM_TX_INT ) {
++                      PRINTK2(KERN_WARNING "%s: TX ERROR handled\n",
++                              dev->name);
++                      smc_tx(dev);
++                      // Acknowledge the interrupt
++                      SMC_ACK_INT( IM_TX_INT );
++              } else if (status & IM_TX_EMPTY_INT ) {
++                      /* update stats */
++                      SMC_SELECT_BANK( 0 );
++                      card_stats = SMC_GET_COUNTER();
++                      /* single collisions */
++                      lp->stats.collisions += card_stats & 0xF;
++                      card_stats >>= 4;
++                      /* multiple collisions */
++                      lp->stats.collisions += card_stats & 0xF;
++
++                      /* these are for when linux supports these statistics */
++
++                      SMC_SELECT_BANK( 2 );
++                      PRINTK2(KERN_WARNING "%s: TX_BUFFER_EMPTY handled\n",
++                              dev->name);
++                      // Acknowledge the interrupt
++                      SMC_ACK_INT( IM_TX_EMPTY_INT );
++                      mask &= ~IM_TX_EMPTY_INT;
++                      lp->stats.tx_packets += lp->packets_waiting;
++                      lp->packets_waiting = 0;
++
++              } else if (status & IM_ALLOC_INT ) {
++                      PRINTK2(KERN_DEBUG "%s: Allocation interrupt \n",
++                              dev->name);
++                      /* clear this interrupt so it doesn't happen again */
++                      mask &= ~IM_ALLOC_INT;
++
++                      smc_hardware_send_packet( dev );
++
++                      /* enable xmit interrupts based on this */
++                      mask |= ( IM_TX_EMPTY_INT | IM_TX_INT );
++
++                      /* and let the card send more packets to me */
++                      netif_wake_queue(dev);
++
++                      PRINTK2("%s: Handoff done successfully.\n",
++                              dev->name);
++              } else if (status & IM_RX_OVRN_INT ) {
++                      lp->stats.rx_errors++;
++                      lp->stats.rx_fifo_errors++;
++                      // Acknowledge the interrupt
++                      SMC_ACK_INT( IM_RX_OVRN_INT );
++              } else if (status & IM_EPH_INT ) {
++                      PRINTK("%s: UNSUPPORTED: EPH INTERRUPT \n",
++                              dev->name);
++              } else if (status & IM_MDINT ) {
++                      smc_phy_interrupt(dev);
++                      // Acknowledge the interrupt
++                      SMC_ACK_INT( IM_MDINT );
++              } else if (status & IM_ERCV_INT ) {
++                      PRINTK("%s: UNSUPPORTED: ERCV INTERRUPT \n",
++                              dev->name);
++                      // Acknowledge the interrupt
++                      SMC_ACK_INT( IM_ERCV_INT );
++              }
++      } while ( timeout -- );
++
++
++      /* restore register states */
++
++      SMC_SELECT_BANK( 2 );
++
++      SMC_SET_INT_MASK( mask );
++
++      PRINTK3( KERN_WARNING "%s: MASK is now %x \n", dev->name, mask);
++      SMC_SET_PTR( saved_pointer );
++
++      SMC_SELECT_BANK( saved_bank );
++
++      PRINTK3("%s: Interrupt done\n", dev->name);
++      return;
++}
++
++/*-------------------------------------------------------------
++ .
++ . smc_rcv -  receive a packet from the card
++ .
++ . There is ( at least ) a packet waiting to be read from
++ . chip-memory.
++ .
++ . o Read the status
++ . o If an error, record it
++ . o otherwise, read in the packet
++ --------------------------------------------------------------
++*/
++static void smc_rcv(struct net_device *dev)
++{
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++      unsigned long ioaddr  = dev->base_addr;
++      int     packet_number;
++      word    status;
++      word    packet_length;
++
++      PRINTK3("%s:smc_rcv\n", dev->name);
++
++      /* assume bank 2 */
++
++      packet_number = SMC_GET_RXFIFO();
++
++      if ( packet_number & RXFIFO_REMPTY ) {
++
++              /* we got called , but nothing was on the FIFO */
++              PRINTK("%s: WARNING: smc_rcv with nothing on FIFO. \n",
++                      dev->name);
++              /* don't need to restore anything */
++              return;
++      }
++
++      /*  start reading from the start of the packet */
++      SMC_SET_PTR( PTR_READ | PTR_RCV | PTR_AUTOINC );
++
++      /* First two words are status and packet_length */
++      status          = SMC_inw( ioaddr + DATA_REG );
++      packet_length   = SMC_inw( ioaddr + DATA_REG );
++
++      packet_length &= 0x07ff;  /* mask off top bits */
++
++      PRINTK2("RCV: STATUS %4x LENGTH %4x\n", status, packet_length );
++
++      if ( !(status & RS_ERRORS ) ){
++              /* do stuff to make a new packet */
++              struct sk_buff  * skb;
++              byte            * data;
++
++              /* set multicast stats */
++              if ( status & RS_MULTICAST )
++                      lp->stats.multicast++;
++
++              // Allocate enough memory for entire receive frame, to be safe
++              skb = dev_alloc_skb( packet_length );
++
++              /* Adjust for having already read the first two words */
++              packet_length -= 4;
++
++              if ( skb == NULL ) {
++                      printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
++                              dev->name);
++                      lp->stats.rx_dropped++;
++                      goto done;
++              }
++
++              /*
++               ! This should work without alignment, but it could be
++               ! in the worse case
++              */
++
++              skb_reserve( skb, 2 );   /* 16 bit alignment */
++
++              skb->dev = dev;
++
++              // set odd length for bug in LAN91C111,
++              // which never sets RS_ODDFRAME
++              data = skb_put( skb, packet_length + 1 );
++
++#ifdef CONFIG_SMC91111_USE_32_BIT
++              PRINTK3(" Reading %d dwords (and %d bytes) \n",
++                      packet_length >> 2, packet_length & 3 );
++              /* QUESTION:  Like in the TX routine, do I want
++                 to send the DWORDs or the bytes first, or some
++                 mixture.  A mixture might improve already slow PIO
++                 performance  */
++              SMC_insl(ioaddr + DATA_REG , data, packet_length >> 2 );
++              /* read the left over bytes */
++#ifdef CONFIG_SMC91111_USE_8_BIT
++              SMC_insb( ioaddr + DATA_REG, data + (packet_length & 0xFFFFFC),
++                        packet_length & 0x3  );
++#else
++              if (packet_length & 0x3)
++              {
++                      unsigned long remaining_data;
++                      insl(ioaddr + DATA_REG , &remaining_data, 1);
++                      memcpy(data + (packet_length & 0xFFFFFC),
++                             &remaining_data, packet_length & 0x3  );
++              }
++#endif // CONFIG_SMC91111_USE_8_BIT
++#else
++              PRINTK3(" Reading %d words and %d byte(s) \n",
++                      (packet_length >> 1 ), packet_length & 1 );
++              SMC_insw(ioaddr + DATA_REG , data, packet_length >> 1);
++
++#endif // CONFIG_SMC91111_USE_32_BIT
++
++#if   SMC_DEBUG > 2
++              printk("Receiving Packet\n");
++              print_packet( data, packet_length );
++#endif
++
++              skb->protocol = eth_type_trans(skb, dev );
++              netif_rx(skb);
++              dev->last_rx = jiffies;
++              lp->stats.rx_packets++;
++              lp->stats.rx_bytes += packet_length;
++      } else {
++              /* error ... */
++              lp->stats.rx_errors++;
++
++              if ( status & RS_ALGNERR )  lp->stats.rx_frame_errors++;
++              if ( status & (RS_TOOSHORT | RS_TOOLONG ) )
++                      lp->stats.rx_length_errors++;
++              if ( status & RS_BADCRC)        lp->stats.rx_crc_errors++;
++      }
++
++      while ( SMC_GET_MMU_CMD() & MC_BUSY )
++              udelay(1); // Wait until not busy
++
++done:
++      /*  error or good, tell the card to get rid of this packet */
++      SMC_SET_MMU_CMD( MC_RELEASE );
++}
++
++
++/*************************************************************************
++ . smc_tx
++ .
++ . Purpose:  Handle a transmit error message.   This will only be called
++ .   when an error, because of the AUTO_RELEASE mode.
++ .
++ . Algorithm:
++ .    Save pointer and packet no
++ .    Get the packet no from the top of the queue
++ .    check if it's valid ( if not, is this an error??? )
++ .    read the status word
++ .    record the error
++ .    ( resend?  Not really, since we don't want old packets around )
++ .    Restore saved values
++ ************************************************************************/
++static void smc_tx( struct net_device * dev )
++{
++      unsigned long  ioaddr = dev->base_addr;
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++      byte saved_packet;
++      byte packet_no;
++      word tx_status;
++
++
++      PRINTK3("%s:smc_tx\n", dev->name);
++
++      /* assume bank 2  */
++
++      saved_packet = SMC_GET_PN();
++      packet_no = SMC_GET_RXFIFO();
++      packet_no &= 0x7F;
++
++      /* If the TX FIFO is empty then nothing to do */
++      if ( packet_no & TXFIFO_TEMPTY )
++              return;
++
++      /* select this as the packet to read from */
++      SMC_SET_PN( packet_no );
++
++      /* read the first word (status word) from this packet */
++      SMC_SET_PTR( PTR_AUTOINC | PTR_READ );
++
++      tx_status = SMC_inw( ioaddr + DATA_REG );
++      PRINTK3("%s: TX DONE STATUS: %4x \n", dev->name, tx_status);
++
++      lp->stats.tx_errors++;
++      if ( tx_status & TS_LOSTCAR ) lp->stats.tx_carrier_errors++;
++      if ( tx_status & TS_LATCOL  ) {
++              printk(KERN_DEBUG
++                      "%s: Late collision occurred on last xmit.\n",
++                      dev->name);
++              lp->stats.tx_window_errors++;
++              lp->ctl_forcol = 0; // Reset forced collsion
++      }
++#if 0
++      if ( tx_status & TS_16COL ) { ... }
++#endif
++
++      if ( tx_status & TS_SUCCESS ) {
++              printk("%s: Successful packet caused interrupt \n", dev->name);
++      }
++      /* re-enable transmit */
++      SMC_SELECT_BANK( 0 );
++      SMC_SET_TCR( SMC_GET_TCR() | TCR_ENABLE );
++
++      /* kill the packet */
++      SMC_SELECT_BANK( 2 );
++      SMC_SET_MMU_CMD( MC_FREEPKT );
++
++      /* one less packet waiting for me */
++      lp->packets_waiting--;
++
++      /* Don't change Packet Number Reg until busy bit is cleared */
++      /* Per LAN91C111 Spec, Page 50 */
++      while ( SMC_GET_MMU_CMD() & MC_BUSY );
++
++      SMC_SET_PN( saved_packet );
++      return;
++}
++
++
++/*----------------------------------------------------
++ . smc_close
++ .
++ . this makes the board clean up everything that it can
++ . and not talk to the outside world.   Caused by
++ . an 'ifconfig ethX down'
++ .
++ -----------------------------------------------------*/
++static int smc_close(struct net_device *dev)
++{
++      PRINTK2("%s:smc_close\n", dev->name);
++
++      netif_stop_queue(dev);
++
++#ifdef CONFIG_SYSCTL
++      smc_sysctl_unregister(dev);
++#endif /* CONFIG_SYSCTL */
++
++      /* clear everything */
++      smc_shutdown( dev->base_addr );
++
++      /* Update the statistics here. */
++      return 0;
++}
++
++/*------------------------------------------------------------
++ . Get the current statistics.
++ . This may be called with the card open or closed.
++ .-------------------------------------------------------------*/
++static struct net_device_stats* smc_query_statistics(struct net_device *dev) {
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++
++      PRINTK2("%s:smc_query_statistics\n", dev->name);
++
++      return &lp->stats;
++}
++
++/*-----------------------------------------------------------
++ . smc_set_multicast_list
++ .
++ . This routine will, depending on the values passed to it,
++ . either make it accept multicast packets, go into
++ . promiscuous mode ( for TCPDUMP and cousins ) or accept
++ . a select set of multicast packets
++*/
++static void smc_set_multicast_list(struct net_device *dev)
++{
++      unsigned long ioaddr = dev->base_addr;
++
++      PRINTK2("%s:smc_set_multicast_list\n", dev->name);
++
++      SMC_SELECT_BANK(0);
++      if ( dev->flags & IFF_PROMISC ) {
++              PRINTK2("%s:smc_set_multicast_list:RCR_PRMS\n", dev->name);
++              SMC_SET_RCR( SMC_GET_RCR() | RCR_PRMS );
++      }
++
++/* BUG?  I never disable promiscuous mode if multicasting was turned on.
++   Now, I turn off promiscuous mode, but I don't do anything to multicasting
++   when promiscuous mode is turned on.
++*/
++
++      /* Here, I am setting this to accept all multicast packets.
++         I don't need to zero the multicast table, because the flag is
++         checked before the table is
++      */
++      else if (dev->flags & IFF_ALLMULTI) {
++              SMC_SET_RCR( SMC_GET_RCR() | RCR_ALMUL );
++              PRINTK2("%s:smc_set_multicast_list:RCR_ALMUL\n", dev->name);
++      }
++
++      /* We just get all multicast packets even if we only want them
++       . from one source.  This will be changed at some future
++       . point. */
++      else if (dev->mc_count )  {
++              /* support hardware multicasting */
++
++              /* be sure I get rid of flags I might have set */
++              SMC_SET_RCR( SMC_GET_RCR() & ~(RCR_PRMS | RCR_ALMUL) );
++              /* NOTE: this has to set the bank, so make sure it is the
++                 last thing called.  The bank is set to zero at the top */
++              smc_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
++      } else  {
++              PRINTK2("%s:smc_set_multicast_list:~(RCR_PRMS|RCR_ALMUL)\n",
++                      dev->name);
++              SMC_SET_RCR( SMC_GET_RCR() & ~(RCR_PRMS | RCR_ALMUL) );
++
++              /*
++                since I'm disabling all multicast entirely, I need to
++                clear the multicast list
++              */
++              SMC_SELECT_BANK( 3 );
++              SMC_CLEAR_MCAST();
++      }
++}
++
++/*------------------------------------------------------------
++ . Cleanup when module is removed with rmmod
++ .-------------------------------------------------------------*/
++static void __exit smc_cleanup(void)
++{
++      /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
++      unregister_netdev(global_dev);
++
++      free_irq(global_dev->irq, global_dev);
++      release_region(global_dev->base_addr, SMC_IO_EXTENT);
++
++#ifndef CONFIG_ISA
++      iounmap((void *)global_dev->base_addr);
++#endif
++
++      kfree(global_dev);
++      global_dev = NULL;
++}
++
++module_init(smc_init);
++module_exit(smc_cleanup);
++
++
++#ifdef CONFIG_SYSCTL
++/*------------------------------------------------------------
++ . Modify a bit in the LAN91C111 register set
++ .-------------------------------------------------------------*/
++static word smc_modify_regbit(int bank, unsigned long ioaddr, int reg,
++      unsigned int bit, int val)
++{
++      word regval;
++
++      SMC_SELECT_BANK( bank );
++
++      regval = SMC_inw( ioaddr+reg );
++      if (val)
++              regval |= bit;
++      else
++              regval &= ~bit;
++
++      SMC_outw( regval, ioaddr );
++      return(regval);
++}
++
++
++/*------------------------------------------------------------
++ . Retrieve a bit in the LAN91C111 register set
++ .-------------------------------------------------------------*/
++static int smc_get_regbit(int bank, unsigned long ioaddr,
++                        int reg, unsigned int bit)
++{
++      SMC_SELECT_BANK( bank );
++      if ( SMC_inw( ioaddr+reg ) & bit)
++              return(1);
++      else
++              return(0);
++}
++
++
++/*------------------------------------------------------------
++ . Modify a LAN91C111 register (word access only)
++ .-------------------------------------------------------------*/
++static void smc_modify_reg(int bank, unsigned long ioaddr,
++                         int reg, word val)
++{
++      SMC_SELECT_BANK( bank );
++      SMC_outw( val, ioaddr+reg );
++}
++
++
++/*------------------------------------------------------------
++ . Retrieve a LAN91C111 register (word access only)
++ .-------------------------------------------------------------*/
++static int smc_get_reg(int bank, unsigned long ioaddr,
++                     int reg)
++{
++      SMC_SELECT_BANK( bank );
++      return(SMC_inw( ioaddr+reg ));
++}
++
++
++static const char smc_info_string[] =
++"\n"
++"info           Provides this information blurb\n"
++"swver          Prints the software version information of this driver\n"
++"autoneg        Auto-negotiate Mode = 1\n"
++"rspeed         Requested Speed, 100=100Mbps, 10=10Mpbs\n"
++"rfduplx        Requested Full Duplex Operation\n"
++"aspeed         Actual Speed, 100=100Mbps, 10=10Mpbs\n"
++"afduplx        Actual Full Duplex Operation\n"
++"lnkfail        PHY Link Failure when 1\n"
++"miiop          External MII when 1, Internal PHY when 0\n"
++"swfdup         Switched Full Duplex Mode (allowed only in MII operation)\n"
++"ephloop        EPH Block Loopback\n"
++"forcol         Force a collision\n"
++"filtcar        Filter leading edge of carrier sense for 12 bit times\n"
++"freemem        Free buffer memory in bytes\n"
++"totmem         Total buffer memory in bytes\n"
++"leda           Output of LED-A (green)\n"
++"ledb           Output of LED-B (yellow)\n"
++"chiprev        Revision ID of the LAN91C111 chip\n"
++"";
++
++/*------------------------------------------------------------
++ . Sysctl handler for all integer parameters
++ .-------------------------------------------------------------*/
++static int smc_sysctl_handler(ctl_table *ctl, int write, struct file * filp,
++                              void *buffer, size_t *lenp)
++{
++      struct net_device *dev = (struct net_device*)ctl->extra1;
++      struct smc_local *lp = (struct smc_local *)ctl->extra2;
++      unsigned long ioaddr = dev->base_addr;
++      int *valp = ctl->data;
++      int val;
++      int ret;
++
++      // Update parameters from the real registers
++      switch (ctl->ctl_name)
++      {
++      case CTL_SMC_FORCOL:
++              *valp = smc_get_regbit(0, ioaddr, TCR_REG, TCR_FORCOL);
++              break;
++
++      case CTL_SMC_FREEMEM:
++              *valp = ( (word)smc_get_reg(0, ioaddr, MIR_REG) >> 8 )
++                      * LAN91C111_MEMORY_MULTIPLIER;
++              break;
++
++
++      case CTL_SMC_TOTMEM:
++              *valp = ( smc_get_reg(0, ioaddr, MIR_REG) & (word)0x00ff )
++                      * LAN91C111_MEMORY_MULTIPLIER;
++              break;
++
++      case CTL_SMC_CHIPREV:
++              *valp = smc_get_reg(3, ioaddr, REV_REG);
++              break;
++
++      case CTL_SMC_AFDUPLX:
++              *valp = (lp->lastPhy18 & PHY_INT_DPLXDET) ? 1 : 0;
++              break;
++
++      case CTL_SMC_ASPEED:
++              *valp = (lp->lastPhy18 & PHY_INT_SPDDET) ? 100 : 10;
++              break;
++
++      case CTL_SMC_LNKFAIL:
++              *valp = (lp->lastPhy18 & PHY_INT_LNKFAIL) ? 1 : 0;
++              break;
++
++      case CTL_SMC_LEDA:
++              *valp = (lp->rpc_cur_mode >> RPC_LSXA_SHFT) & (word)0x0007;
++              break;
++
++      case CTL_SMC_LEDB:
++              *valp = (lp->rpc_cur_mode >> RPC_LSXB_SHFT) & (word)0x0007;
++              break;
++
++      case CTL_SMC_MIIOP:
++              *valp = smc_get_regbit(1, ioaddr, CONFIG_REG, CONFIG_EXT_PHY);
++              break;
++
++#if SMC_DEBUG > 1
++      case CTL_SMC_REG_BSR:   // Bank Select
++              *valp = smc_get_reg(0, ioaddr, BSR_REG);
++              break;
++
++      case CTL_SMC_REG_TCR:   // Transmit Control
++              *valp = smc_get_reg(0, ioaddr, TCR_REG);
++              break;
++
++      case CTL_SMC_REG_ESR:   // EPH Status
++              *valp = smc_get_reg(0, ioaddr, EPH_STATUS_REG);
++              break;
++
++      case CTL_SMC_REG_RCR:   // Receive Control
++              *valp = smc_get_reg(0, ioaddr, RCR_REG);
++              break;
++
++      case CTL_SMC_REG_CTRR:  // Counter
++              *valp = smc_get_reg(0, ioaddr, COUNTER_REG);
++              break;
++
++      case CTL_SMC_REG_MIR:   // Memory Information
++              *valp = smc_get_reg(0, ioaddr, MIR_REG);
++              break;
++
++      case CTL_SMC_REG_RPCR:  // Receive/Phy Control
++              *valp = smc_get_reg(0, ioaddr, RPC_REG);
++              break;
++
++      case CTL_SMC_REG_CFGR:  // Configuration
++              *valp = smc_get_reg(1, ioaddr, CONFIG_REG);
++              break;
++
++      case CTL_SMC_REG_BAR:   // Base Address
++              *valp = smc_get_reg(1, ioaddr, BASE_REG);
++              break;
++
++      case CTL_SMC_REG_IAR0:  // Individual Address
++              *valp = smc_get_reg(1, ioaddr, ADDR0_REG);
++              break;
++
++      case CTL_SMC_REG_IAR1:  // Individual Address
++              *valp = smc_get_reg(1, ioaddr, ADDR1_REG);
++              break;
++
++      case CTL_SMC_REG_IAR2:  // Individual Address
++              *valp = smc_get_reg(1, ioaddr, ADDR2_REG);
++              break;
++
++      case CTL_SMC_REG_GPR:   // General Purpose
++              *valp = smc_get_reg(1, ioaddr, GP_REG);
++              break;
++
++      case CTL_SMC_REG_CTLR:  // Control
++              *valp = smc_get_reg(1, ioaddr, CTL_REG);
++              break;
++
++      case CTL_SMC_REG_MCR:   // MMU Command
++              *valp = smc_get_reg(2, ioaddr, MMU_CMD_REG);
++              break;
++
++      case CTL_SMC_REG_PNR:   // Packet Number
++              *valp = smc_get_reg(2, ioaddr, PN_REG);
++              break;
++
++      case CTL_SMC_REG_FPR:   // Allocation Result/FIFO Ports
++              *valp = smc_get_reg(2, ioaddr, RXFIFO_REG);
++              break;
++
++      case CTL_SMC_REG_PTR:   // Pointer
++              *valp = smc_get_reg(2, ioaddr, PTR_REG);
++              break;
++
++      case CTL_SMC_REG_DR:    // Data
++              *valp = smc_get_reg(2, ioaddr, DATA_REG);
++              break;
++
++      case CTL_SMC_REG_ISR:   // Interrupt Status/Mask
++              *valp = smc_get_reg(2, ioaddr, INT_REG);
++              break;
++
++      case CTL_SMC_REG_MTR1:  // Multicast Table Entry 1
++              *valp = smc_get_reg(3, ioaddr, MCAST_REG1);
++              break;
++
++      case CTL_SMC_REG_MTR2:  // Multicast Table Entry 2
++              *valp = smc_get_reg(3, ioaddr, MCAST_REG2);
++              break;
++
++      case CTL_SMC_REG_MTR3:  // Multicast Table Entry 3
++              *valp = smc_get_reg(3, ioaddr, MCAST_REG3);
++              break;
++
++      case CTL_SMC_REG_MTR4:  // Multicast Table Entry 4
++              *valp = smc_get_reg(3, ioaddr, MCAST_REG4);
++              break;
++
++      case CTL_SMC_REG_MIIR:  // Management Interface
++              *valp = smc_get_reg(3, ioaddr, MII_REG);
++              break;
++
++      case CTL_SMC_REG_REVR:  // Revision
++              *valp = smc_get_reg(3, ioaddr, REV_REG);
++              break;
++
++      case CTL_SMC_REG_ERCVR: // Early RCV
++              *valp = smc_get_reg(3, ioaddr, ERCV_REG);
++              break;
++
++      case CTL_SMC_REG_EXTR:  // External
++              *valp = smc_get_reg(7, ioaddr, EXT_REG);
++              break;
++
++      case CTL_SMC_PHY_CTRL:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_CNTL_REG);
++              break;
++
++      case CTL_SMC_PHY_STAT:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_STAT_REG);
++              break;
++
++      case CTL_SMC_PHY_ID1:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_ID1_REG);
++              break;
++
++      case CTL_SMC_PHY_ID2:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_ID2_REG);
++              break;
++
++      case CTL_SMC_PHY_ADC:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_AD_REG);
++              break;
++
++      case CTL_SMC_PHY_REMC:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_RMT_REG);
++              break;
++
++      case CTL_SMC_PHY_CFG1:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_CFG1_REG);
++              break;
++
++      case CTL_SMC_PHY_CFG2:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_CFG2_REG);
++              break;
++
++      case CTL_SMC_PHY_INT:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_INT_REG);
++              break;
++
++      case CTL_SMC_PHY_MASK:
++              *valp = smc_read_phy_register(ioaddr, lp->phyaddr,
++                      PHY_MASK_REG);
++              break;
++
++#endif // SMC_DEBUG > 1
++
++      default:
++              // Just ignore unsupported parameters
++              break;
++      }
++
++      // Save old state
++      val = *valp;
++
++      // Perform the generic integer operation
++      if ((ret = proc_dointvec(ctl, write, filp, buffer, lenp)) != 0)
++              return(ret);
++
++      // Write changes out to the registers
++      if (write && *valp != val) {
++
++              val = *valp;
++              switch (ctl->ctl_name) {
++
++              case CTL_SMC_SWFDUP:
++                      if (val)
++                              lp->tcr_cur_mode |= TCR_SWFDUP;
++                      else
++                              lp->tcr_cur_mode &= ~TCR_SWFDUP;
++
++                      smc_modify_regbit(0, ioaddr, TCR_REG, TCR_SWFDUP, val);
++                      break;
++
++              case CTL_SMC_EPHLOOP:
++                      if (val)
++                              lp->tcr_cur_mode |= TCR_EPH_LOOP;
++                      else
++                              lp->tcr_cur_mode &= ~TCR_EPH_LOOP;
++
++                      smc_modify_regbit(0, ioaddr, TCR_REG, TCR_EPH_LOOP, val);
++                      break;
++
++              case CTL_SMC_FORCOL:
++                      if (val)
++                              lp->tcr_cur_mode |= TCR_FORCOL;
++                      else
++                              lp->tcr_cur_mode &= ~TCR_FORCOL;
++
++                      // Update the EPH block
++                      smc_modify_regbit(0, ioaddr, TCR_REG, TCR_FORCOL, val);
++                      break;
++
++              case CTL_SMC_FILTCAR:
++                      if (val)
++                              lp->rcr_cur_mode |= RCR_FILT_CAR;
++                      else
++                              lp->rcr_cur_mode &= ~RCR_FILT_CAR;
++
++                      // Update the EPH block
++                      smc_modify_regbit(0, ioaddr, RCR_REG, RCR_FILT_CAR, val);
++                      break;
++
++              case CTL_SMC_RFDUPLX:
++                      // Disallow changes if in auto-negotiation mode
++                      if (lp->ctl_autoneg)
++                              break;
++
++                      if (val)
++                              lp->rpc_cur_mode |= RPC_DPLX;
++                      else
++                              lp->rpc_cur_mode &= ~RPC_DPLX;
++
++                      // Reconfigure the PHY
++                      smc_phy_configure(dev);
++
++                      break;
++
++              case CTL_SMC_RSPEED:
++                      // Disallow changes if in auto-negotiation mode
++                      if (lp->ctl_autoneg)
++                              break;
++
++                      if (val > 10)
++                              lp->rpc_cur_mode |= RPC_SPEED;
++                      else
++                              lp->rpc_cur_mode &= ~RPC_SPEED;
++
++                      // Reconfigure the PHY
++                      smc_phy_configure(dev);
++
++                      break;
++
++              case CTL_SMC_AUTONEG:
++                      if (val)
++                              lp->rpc_cur_mode |= RPC_ANEG;
++                      else
++                              lp->rpc_cur_mode &= ~RPC_ANEG;
++
++                      // Reconfigure the PHY
++                      smc_phy_configure(dev);
++
++                      break;
++
++              case CTL_SMC_LEDA:
++                      val &= 0x07; // Restrict to 3 ls bits
++                      lp->rpc_cur_mode &= ~(word)(0x07<<RPC_LSXA_SHFT);
++                      lp->rpc_cur_mode |= (word)(val<<RPC_LSXA_SHFT);
++
++                      // Update the Internal PHY block
++                      smc_modify_reg(0, ioaddr, RPC_REG, lp->rpc_cur_mode);
++                      break;
++
++              case CTL_SMC_LEDB:
++                      val &= 0x07; // Restrict to 3 ls bits
++                      lp->rpc_cur_mode &= ~(word)(0x07<<RPC_LSXB_SHFT);
++                      lp->rpc_cur_mode |= (word)(val<<RPC_LSXB_SHFT);
++
++                      // Update the Internal PHY block
++                      smc_modify_reg(0, ioaddr, RPC_REG, lp->rpc_cur_mode);
++                      break;
++
++              case CTL_SMC_MIIOP:
++                      // Update the Internal PHY block
++                      smc_modify_regbit(1, ioaddr, CONFIG_REG,
++                              CONFIG_EXT_PHY, val);
++                      break;
++
++#if SMC_DEBUG > 1
++              case CTL_SMC_REG_BSR:   // Bank Select
++                      smc_modify_reg(0, ioaddr, BSR_REG, val);
++                      break;
++
++              case CTL_SMC_REG_TCR:   // Transmit Control
++                      smc_modify_reg(0, ioaddr, TCR_REG, val);
++                      break;
++
++              case CTL_SMC_REG_ESR:   // EPH Status
++                      smc_modify_reg(0, ioaddr, EPH_STATUS_REG, val);
++                      break;
++
++              case CTL_SMC_REG_RCR:   // Receive Control
++                      smc_modify_reg(0, ioaddr, RCR_REG, val);
++                      break;
++
++              case CTL_SMC_REG_CTRR:  // Counter
++                      smc_modify_reg(0, ioaddr, COUNTER_REG, val);
++                      break;
++
++              case CTL_SMC_REG_MIR:   // Memory Information
++                      smc_modify_reg(0, ioaddr, MIR_REG, val);
++                      break;
++
++              case CTL_SMC_REG_RPCR:  // Receive/Phy Control
++                      smc_modify_reg(0, ioaddr, RPC_REG, val);
++                      break;
++
++              case CTL_SMC_REG_CFGR:  // Configuration
++                      smc_modify_reg(1, ioaddr, CONFIG_REG, val);
++                      break;
++
++              case CTL_SMC_REG_BAR:   // Base Address
++                      smc_modify_reg(1, ioaddr, BASE_REG, val);
++                      break;
++
++              case CTL_SMC_REG_IAR0:  // Individual Address
++                      smc_modify_reg(1, ioaddr, ADDR0_REG, val);
++                      break;
++
++              case CTL_SMC_REG_IAR1:  // Individual Address
++                      smc_modify_reg(1, ioaddr, ADDR1_REG, val);
++                      break;
++
++              case CTL_SMC_REG_IAR2:  // Individual Address
++                      smc_modify_reg(1, ioaddr, ADDR2_REG, val);
++                      break;
++
++              case CTL_SMC_REG_GPR:   // General Purpose
++                      smc_modify_reg(1, ioaddr, GP_REG, val);
++                      break;
++
++              case CTL_SMC_REG_CTLR:  // Control
++                      smc_modify_reg(1, ioaddr, CTL_REG, val);
++                      break;
++
++              case CTL_SMC_REG_MCR:   // MMU Command
++                      smc_modify_reg(2, ioaddr, MMU_CMD_REG, val);
++                      break;
++
++              case CTL_SMC_REG_PNR:   // Packet Number
++                      smc_modify_reg(2, ioaddr, PN_REG, val);
++                      break;
++
++              case CTL_SMC_REG_FPR:   // Allocation Result/FIFO Ports
++                      smc_modify_reg(2, ioaddr, RXFIFO_REG, val);
++                      break;
++
++              case CTL_SMC_REG_PTR:   // Pointer
++                      smc_modify_reg(2, ioaddr, PTR_REG, val);
++                      break;
++
++              case CTL_SMC_REG_DR:    // Data
++                      smc_modify_reg(2, ioaddr, DATA_REG, val);
++                      break;
++
++              case CTL_SMC_REG_ISR:   // Interrupt Status/Mask
++                      smc_modify_reg(2, ioaddr, INT_REG, val);
++                      break;
++
++              case CTL_SMC_REG_MTR1:  // Multicast Table Entry 1
++                      smc_modify_reg(3, ioaddr, MCAST_REG1, val);
++                      break;
++
++              case CTL_SMC_REG_MTR2:  // Multicast Table Entry 2
++                      smc_modify_reg(3, ioaddr, MCAST_REG2, val);
++                      break;
++
++              case CTL_SMC_REG_MTR3:  // Multicast Table Entry 3
++                      smc_modify_reg(3, ioaddr, MCAST_REG3, val);
++                      break;
++
++              case CTL_SMC_REG_MTR4:  // Multicast Table Entry 4
++                      smc_modify_reg(3, ioaddr, MCAST_REG4, val);
++                      break;
++
++              case CTL_SMC_REG_MIIR:  // Management Interface
++                      smc_modify_reg(3, ioaddr, MII_REG, val);
++                      break;
++
++              case CTL_SMC_REG_REVR:  // Revision
++                      smc_modify_reg(3, ioaddr, REV_REG, val);
++                      break;
++
++              case CTL_SMC_REG_ERCVR: // Early RCV
++                      smc_modify_reg(3, ioaddr, ERCV_REG, val);
++                      break;
++
++              case CTL_SMC_REG_EXTR:  // External
++                      smc_modify_reg(7, ioaddr, EXT_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_CTRL:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_CNTL_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_STAT:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_STAT_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_ID1:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_ID1_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_ID2:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_ID2_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_ADC:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_AD_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_REMC:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_RMT_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_CFG1:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_CFG1_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_CFG2:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_CFG2_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_INT:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_INT_REG, val);
++                      break;
++
++              case CTL_SMC_PHY_MASK:
++                      smc_write_phy_register(ioaddr, lp->phyaddr,
++                              PHY_MASK_REG, val);
++                      break;
++
++#endif // SMC_DEBUG > 1
++
++              default:
++                      // Just ignore unsupported parameters
++                      break;
++              } // end switch
++
++      } // end if
++
++        return ret;
++}
++
++
++#ifdef MODULE
++/*
++ * This is called as the fill_inode function when an inode
++ * is going into (fill = 1) or out of service (fill = 0).
++ * We use it here to manage the module use counts.
++ *
++ * Note: only the top-level directory needs to do this; if
++ * a lower level is referenced, the parent will be as well.
++ */
++static void smc_procfs_modcount(struct inode *inode, int fill)
++{
++      if (fill)
++              MOD_INC_USE_COUNT;
++      else
++              MOD_DEC_USE_COUNT;
++}
++#endif // MODULE
++
++/*------------------------------------------------------------
++ . Sysctl registration function for all parameters (files)
++ .-------------------------------------------------------------*/
++static void smc_sysctl_register(struct net_device *dev)
++{
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++      static int ctl_name = CTL_SMC;
++      ctl_table* ct;
++      int i;
++
++      // Make sure the ctl_tables start out as all zeros
++      memset(lp->root_table, 0, sizeof lp->root_table);
++      memset(lp->eth_table, 0, sizeof lp->eth_table);
++      memset(lp->param_table, 0, sizeof lp->param_table);
++
++      // Initialize the root table
++      ct = lp->root_table;
++      ct->ctl_name = CTL_DEV;
++      ct->procname = "dev";
++      ct->maxlen = 0;
++      ct->mode = 0555;
++      ct->child = lp->eth_table;
++      // remaining fields are zero
++
++      // Initialize the ethX table (this device's table)
++      ct = lp->eth_table;
++      ct->ctl_name = ctl_name++; // Must be unique
++      ct->procname = dev->name;
++      ct->maxlen = 0;
++      ct->mode = 0555;
++      ct->child = lp->param_table;
++      // remaining fields are zero
++
++      // Initialize the parameter (files) table
++      // Make sure the last entry remains null
++      ct = lp->param_table;
++      for (i = 0; i < (CTL_SMC_LAST_ENTRY-1); ++i) {
++              // Initialize fields common to all table entries
++              ct[i].proc_handler = smc_sysctl_handler;
++              ct[i].extra1 = (void*)dev; // Save our device pointer
++              ct[i].extra2 = (void*)lp;  // Save our smc_local data pointer
++      }
++
++      // INFO - this is our only string parameter
++      i = 0;
++      ct[i].proc_handler = proc_dostring; // use default handler
++      ct[i].ctl_name = CTL_SMC_INFO;
++      ct[i].procname = "info";
++      ct[i].data = (void*)smc_info_string;
++      ct[i].maxlen = sizeof smc_info_string;
++      ct[i].mode = 0444; // Read only
++
++      // SWVER
++      ++i;
++      ct[i].proc_handler = proc_dostring; // use default handler
++      ct[i].ctl_name = CTL_SMC_SWVER;
++      ct[i].procname = "swver";
++      ct[i].data = (void*)version;
++      ct[i].maxlen = sizeof version;
++      ct[i].mode = 0444; // Read only
++
++      // SWFDUP
++      ++i;
++      ct[i].ctl_name = CTL_SMC_SWFDUP;
++      ct[i].procname = "swfdup";
++      ct[i].data = (void*)&(lp->ctl_swfdup);
++      ct[i].maxlen = sizeof lp->ctl_swfdup;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // EPHLOOP
++      ++i;
++      ct[i].ctl_name = CTL_SMC_EPHLOOP;
++      ct[i].procname = "ephloop";
++      ct[i].data = (void*)&(lp->ctl_ephloop);
++      ct[i].maxlen = sizeof lp->ctl_ephloop;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // MIIOP
++      ++i;
++      ct[i].ctl_name = CTL_SMC_MIIOP;
++      ct[i].procname = "miiop";
++      ct[i].data = (void*)&(lp->ctl_miiop);
++      ct[i].maxlen = sizeof lp->ctl_miiop;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // AUTONEG
++      ++i;
++      ct[i].ctl_name = CTL_SMC_AUTONEG;
++      ct[i].procname = "autoneg";
++      ct[i].data = (void*)&(lp->ctl_autoneg);
++      ct[i].maxlen = sizeof lp->ctl_autoneg;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // RFDUPLX
++      ++i;
++      ct[i].ctl_name = CTL_SMC_RFDUPLX;
++      ct[i].procname = "rfduplx";
++      ct[i].data = (void*)&(lp->ctl_rfduplx);
++      ct[i].maxlen = sizeof lp->ctl_rfduplx;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // RSPEED
++      ++i;
++      ct[i].ctl_name = CTL_SMC_RSPEED;
++      ct[i].procname = "rspeed";
++      ct[i].data = (void*)&(lp->ctl_rspeed);
++      ct[i].maxlen = sizeof lp->ctl_rspeed;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // AFDUPLX
++      ++i;
++      ct[i].ctl_name = CTL_SMC_AFDUPLX;
++      ct[i].procname = "afduplx";
++      ct[i].data = (void*)&(lp->ctl_afduplx);
++      ct[i].maxlen = sizeof lp->ctl_afduplx;
++      ct[i].mode = 0444; // Read only
++
++      // ASPEED
++      ++i;
++      ct[i].ctl_name = CTL_SMC_ASPEED;
++      ct[i].procname = "aspeed";
++      ct[i].data = (void*)&(lp->ctl_aspeed);
++      ct[i].maxlen = sizeof lp->ctl_aspeed;
++      ct[i].mode = 0444; // Read only
++
++      // LNKFAIL
++      ++i;
++      ct[i].ctl_name = CTL_SMC_LNKFAIL;
++      ct[i].procname = "lnkfail";
++      ct[i].data = (void*)&(lp->ctl_lnkfail);
++      ct[i].maxlen = sizeof lp->ctl_lnkfail;
++      ct[i].mode = 0444; // Read only
++
++      // FORCOL
++      ++i;
++      ct[i].ctl_name = CTL_SMC_FORCOL;
++      ct[i].procname = "forcol";
++      ct[i].data = (void*)&(lp->ctl_forcol);
++      ct[i].maxlen = sizeof lp->ctl_forcol;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // FILTCAR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_FILTCAR;
++      ct[i].procname = "filtcar";
++      ct[i].data = (void*)&(lp->ctl_filtcar);
++      ct[i].maxlen = sizeof lp->ctl_filtcar;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // FREEMEM
++      ++i;
++      ct[i].ctl_name = CTL_SMC_FREEMEM;
++      ct[i].procname = "freemem";
++      ct[i].data = (void*)&(lp->ctl_freemem);
++      ct[i].maxlen = sizeof lp->ctl_freemem;
++      ct[i].mode = 0444; // Read only
++
++      // TOTMEM
++      ++i;
++      ct[i].ctl_name = CTL_SMC_TOTMEM;
++      ct[i].procname = "totmem";
++      ct[i].data = (void*)&(lp->ctl_totmem);
++      ct[i].maxlen = sizeof lp->ctl_totmem;
++      ct[i].mode = 0444; // Read only
++
++      // LEDA
++      ++i;
++      ct[i].ctl_name = CTL_SMC_LEDA;
++      ct[i].procname = "leda";
++      ct[i].data = (void*)&(lp->ctl_leda);
++      ct[i].maxlen = sizeof lp->ctl_leda;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // LEDB
++      ++i;
++      ct[i].ctl_name = CTL_SMC_LEDB;
++      ct[i].procname = "ledb";
++      ct[i].data = (void*)&(lp->ctl_ledb);
++      ct[i].maxlen = sizeof lp->ctl_ledb;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // CHIPREV
++      ++i;
++      ct[i].ctl_name = CTL_SMC_CHIPREV;
++      ct[i].procname = "chiprev";
++      ct[i].data = (void*)&(lp->ctl_chiprev);
++      ct[i].maxlen = sizeof lp->ctl_chiprev;
++      ct[i].mode = 0444; // Read only
++
++#if SMC_DEBUG > 1
++      // REG_BSR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_BSR;
++      ct[i].procname = "reg_bsr";
++      ct[i].data = (void*)&(lp->ctl_reg_bsr);
++      ct[i].maxlen = sizeof lp->ctl_reg_bsr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_TCR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_TCR;
++      ct[i].procname = "reg_tcr";
++      ct[i].data = (void*)&(lp->ctl_reg_tcr);
++      ct[i].maxlen = sizeof lp->ctl_reg_tcr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_ESR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_ESR;
++      ct[i].procname = "reg_esr";
++      ct[i].data = (void*)&(lp->ctl_reg_esr);
++      ct[i].maxlen = sizeof lp->ctl_reg_esr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_RCR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_RCR;
++      ct[i].procname = "reg_rcr";
++      ct[i].data = (void*)&(lp->ctl_reg_rcr);
++      ct[i].maxlen = sizeof lp->ctl_reg_rcr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_CTRR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_CTRR;
++      ct[i].procname = "reg_ctrr";
++      ct[i].data = (void*)&(lp->ctl_reg_ctrr);
++      ct[i].maxlen = sizeof lp->ctl_reg_ctrr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_MIR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_MIR;
++      ct[i].procname = "reg_mir";
++      ct[i].data = (void*)&(lp->ctl_reg_mir);
++      ct[i].maxlen = sizeof lp->ctl_reg_mir;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_RPCR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_RPCR;
++      ct[i].procname = "reg_rpcr";
++      ct[i].data = (void*)&(lp->ctl_reg_rpcr);
++      ct[i].maxlen = sizeof lp->ctl_reg_rpcr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_CFGR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_CFGR;
++      ct[i].procname = "reg_cfgr";
++      ct[i].data = (void*)&(lp->ctl_reg_cfgr);
++      ct[i].maxlen = sizeof lp->ctl_reg_cfgr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_BAR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_BAR;
++      ct[i].procname = "reg_bar";
++      ct[i].data = (void*)&(lp->ctl_reg_bar);
++      ct[i].maxlen = sizeof lp->ctl_reg_bar;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_IAR0
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_IAR0;
++      ct[i].procname = "reg_iar0";
++      ct[i].data = (void*)&(lp->ctl_reg_iar0);
++      ct[i].maxlen = sizeof lp->ctl_reg_iar0;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_IAR1
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_IAR1;
++      ct[i].procname = "reg_iar1";
++      ct[i].data = (void*)&(lp->ctl_reg_iar1);
++      ct[i].maxlen = sizeof lp->ctl_reg_iar1;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_IAR2
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_IAR2;
++      ct[i].procname = "reg_iar2";
++      ct[i].data = (void*)&(lp->ctl_reg_iar2);
++      ct[i].maxlen = sizeof lp->ctl_reg_iar2;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_GPR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_GPR;
++      ct[i].procname = "reg_gpr";
++      ct[i].data = (void*)&(lp->ctl_reg_gpr);
++      ct[i].maxlen = sizeof lp->ctl_reg_gpr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_CTLR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_CTLR;
++      ct[i].procname = "reg_ctlr";
++      ct[i].data = (void*)&(lp->ctl_reg_ctlr);
++      ct[i].maxlen = sizeof lp->ctl_reg_ctlr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_MCR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_MCR;
++      ct[i].procname = "reg_mcr";
++      ct[i].data = (void*)&(lp->ctl_reg_mcr);
++      ct[i].maxlen = sizeof lp->ctl_reg_mcr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_PNR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_PNR;
++      ct[i].procname = "reg_pnr";
++      ct[i].data = (void*)&(lp->ctl_reg_pnr);
++      ct[i].maxlen = sizeof lp->ctl_reg_pnr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_FPR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_FPR;
++      ct[i].procname = "reg_fpr";
++      ct[i].data = (void*)&(lp->ctl_reg_fpr);
++      ct[i].maxlen = sizeof lp->ctl_reg_fpr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_PTR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_PTR;
++      ct[i].procname = "reg_ptr";
++      ct[i].data = (void*)&(lp->ctl_reg_ptr);
++      ct[i].maxlen = sizeof lp->ctl_reg_ptr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_DR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_DR;
++      ct[i].procname = "reg_dr";
++      ct[i].data = (void*)&(lp->ctl_reg_dr);
++      ct[i].maxlen = sizeof lp->ctl_reg_dr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_ISR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_ISR;
++      ct[i].procname = "reg_isr";
++      ct[i].data = (void*)&(lp->ctl_reg_isr);
++      ct[i].maxlen = sizeof lp->ctl_reg_isr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_MTR1
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_MTR1;
++      ct[i].procname = "reg_mtr1";
++      ct[i].data = (void*)&(lp->ctl_reg_mtr1);
++      ct[i].maxlen = sizeof lp->ctl_reg_mtr1;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_MTR2
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_MTR2;
++      ct[i].procname = "reg_mtr2";
++      ct[i].data = (void*)&(lp->ctl_reg_mtr2);
++      ct[i].maxlen = sizeof lp->ctl_reg_mtr2;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_MTR3
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_MTR3;
++      ct[i].procname = "reg_mtr3";
++      ct[i].data = (void*)&(lp->ctl_reg_mtr3);
++      ct[i].maxlen = sizeof lp->ctl_reg_mtr3;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_MTR4
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_MTR4;
++      ct[i].procname = "reg_mtr4";
++      ct[i].data = (void*)&(lp->ctl_reg_mtr4);
++      ct[i].maxlen = sizeof lp->ctl_reg_mtr4;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_MIIR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_MIIR;
++      ct[i].procname = "reg_miir";
++      ct[i].data = (void*)&(lp->ctl_reg_miir);
++      ct[i].maxlen = sizeof lp->ctl_reg_miir;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_REVR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_REVR;
++      ct[i].procname = "reg_revr";
++      ct[i].data = (void*)&(lp->ctl_reg_revr);
++      ct[i].maxlen = sizeof lp->ctl_reg_revr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_ERCVR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_ERCVR;
++      ct[i].procname = "reg_ercvr";
++      ct[i].data = (void*)&(lp->ctl_reg_ercvr);
++      ct[i].maxlen = sizeof lp->ctl_reg_ercvr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // REG_EXTR
++      ++i;
++      ct[i].ctl_name = CTL_SMC_REG_EXTR;
++      ct[i].procname = "reg_extr";
++      ct[i].data = (void*)&(lp->ctl_reg_extr);
++      ct[i].maxlen = sizeof lp->ctl_reg_extr;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY Control
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_CTRL;
++      ct[i].procname = "phy_ctrl";
++      ct[i].data = (void*)&(lp->ctl_phy_ctrl);
++      ct[i].maxlen = sizeof lp->ctl_phy_ctrl;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY Status
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_STAT;
++      ct[i].procname = "phy_stat";
++      ct[i].data = (void*)&(lp->ctl_phy_stat);
++      ct[i].maxlen = sizeof lp->ctl_phy_stat;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY ID1
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_ID1;
++      ct[i].procname = "phy_id1";
++      ct[i].data = (void*)&(lp->ctl_phy_id1);
++      ct[i].maxlen = sizeof lp->ctl_phy_id1;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY ID2
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_ID2;
++      ct[i].procname = "phy_id2";
++      ct[i].data = (void*)&(lp->ctl_phy_id2);
++      ct[i].maxlen = sizeof lp->ctl_phy_id2;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY Advertise Capabilities
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_ADC;
++      ct[i].procname = "phy_adc";
++      ct[i].data = (void*)&(lp->ctl_phy_adc);
++      ct[i].maxlen = sizeof lp->ctl_phy_adc;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY Remote Capabilities
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_REMC;
++      ct[i].procname = "phy_remc";
++      ct[i].data = (void*)&(lp->ctl_phy_remc);
++      ct[i].maxlen = sizeof lp->ctl_phy_remc;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY Configuration 1
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_CFG1;
++      ct[i].procname = "phy_cfg1";
++      ct[i].data = (void*)&(lp->ctl_phy_cfg1);
++      ct[i].maxlen = sizeof lp->ctl_phy_cfg1;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY Configuration 2
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_CFG2;
++      ct[i].procname = "phy_cfg2";
++      ct[i].data = (void*)&(lp->ctl_phy_cfg2);
++      ct[i].maxlen = sizeof lp->ctl_phy_cfg2;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY Interrupt/Status Output
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_INT;
++      ct[i].procname = "phy_int";
++      ct[i].data = (void*)&(lp->ctl_phy_int);
++      ct[i].maxlen = sizeof lp->ctl_phy_int;
++      ct[i].mode = 0644; // Read by all, write by root
++
++      // PHY Interrupt/Status Mask
++      ++i;
++      ct[i].ctl_name = CTL_SMC_PHY_MASK;
++      ct[i].procname = "phy_mask";
++      ct[i].data = (void*)&(lp->ctl_phy_mask);
++      ct[i].maxlen = sizeof lp->ctl_phy_mask;
++      ct[i].mode = 0644; // Read by all, write by root
++
++#endif // SMC_DEBUG > 1
++
++      // Register /proc/sys/dev/ethX
++      lp->sysctl_header = register_sysctl_table(lp->root_table, 1);
++
++#ifdef MODULE
++      // Register our modcount function which adjusts the module count
++      lp->root_table->child->de->fill_inode = smc_procfs_modcount;
++#endif // MODULE
++
++}
++
++
++/*------------------------------------------------------------
++ . Sysctl unregistration when driver is closed
++ .-------------------------------------------------------------*/
++static void smc_sysctl_unregister(struct net_device *dev)
++{
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++
++      unregister_sysctl_table(lp->sysctl_header);
++}
++
++#endif /* endif CONFIG_SYSCTL */
++
++
++//---PHY CONTROL AND CONFIGURATION-----------------------------------------
++
++#if (SMC_DEBUG > 2 )
++
++/*------------------------------------------------------------
++ . Debugging function for viewing MII Management serial bitstream
++ .-------------------------------------------------------------*/
++static void smc_dump_mii_stream(byte* bits, int size)
++{
++      int i;
++
++      printk("BIT#:");
++      for (i = 0; i < size; ++i)
++              printk("%d", i%10);
++
++      printk("\nMDOE:");
++      for (i = 0; i < size; ++i) {
++              if (bits[i] & MII_MDOE)
++                      printk("1");
++              else
++                      printk("0");
++      }
++
++      printk("\nMDO :");
++      for (i = 0; i < size; ++i) {
++              if (bits[i] & MII_MDO)
++                      printk("1");
++              else
++                      printk("0");
++      }
++
++      printk("\nMDI :");
++      for (i = 0; i < size; ++i) {
++              if (bits[i] & MII_MDI)
++                      printk("1");
++              else
++                      printk("0");
++      }
++
++      printk("\n");
++}
++#endif
++
++/*------------------------------------------------------------
++ . Reads a register from the MII Management serial interface
++ .-------------------------------------------------------------*/
++static word smc_read_phy_register(unsigned long ioaddr,
++                                byte phyaddr, byte phyreg)
++{
++      int oldBank;
++      int i;
++      byte mask;
++      word mii_reg;
++      byte bits[64];
++      int clk_idx = 0;
++      int input_idx;
++      word phydata;
++
++      // 32 consecutive ones on MDO to establish sync
++      for (i = 0; i < 32; ++i)
++              bits[clk_idx++] = MII_MDOE | MII_MDO;
++
++      // Start code <01>
++      bits[clk_idx++] = MII_MDOE;
++      bits[clk_idx++] = MII_MDOE | MII_MDO;
++
++      // Read command <10>
++      bits[clk_idx++] = MII_MDOE | MII_MDO;
++      bits[clk_idx++] = MII_MDOE;
++
++      // Output the PHY address, msb first
++      mask = (byte)0x10;
++      for (i = 0; i < 5; ++i) {
++              if (phyaddr & mask)
++                      bits[clk_idx++] = MII_MDOE | MII_MDO;
++              else
++                      bits[clk_idx++] = MII_MDOE;
++
++              // Shift to next lowest bit
++              mask >>= 1;
++      }
++
++      // Output the phy register number, msb first
++      mask = (byte)0x10;
++      for (i = 0; i < 5; ++i) {
++              if (phyreg & mask)
++                      bits[clk_idx++] = MII_MDOE | MII_MDO;
++              else
++                      bits[clk_idx++] = MII_MDOE;
++
++              // Shift to next lowest bit
++              mask >>= 1;
++      }
++
++      // Tristate and turnaround (2 bit times)
++      bits[clk_idx++] = 0;
++      //bits[clk_idx++] = 0;
++
++      // Input starts at this bit time
++      input_idx = clk_idx;
++
++      // Will input 16 bits
++      for (i = 0; i < 16; ++i)
++              bits[clk_idx++] = 0;
++
++      // Final clock bit
++      bits[clk_idx++] = 0;
++
++      // Save the current bank
++      oldBank = SMC_CURRENT_BANK();
++
++      // Select bank 3
++      SMC_SELECT_BANK( 3 );
++
++      // Get the current MII register value
++      mii_reg = SMC_GET_MII();
++
++      // Turn off all MII Interface bits
++      mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
++
++      // Clock all 64 cycles
++      for (i = 0; i < sizeof bits; ++i) {
++              // Clock Low - output data
++              SMC_SET_MII( mii_reg | bits[i] );
++              udelay(50);
++
++
++              // Clock Hi - input data
++              SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );
++              udelay(50);
++              bits[i] |= SMC_GET_MII() & MII_MDI;
++      }
++
++      // Return to idle state
++      // Set clock to low, data to low, and output tristated
++      SMC_SET_MII( mii_reg );
++      udelay(50);
++
++      // Restore original bank select
++      SMC_SELECT_BANK( oldBank );
++
++      // Recover input data
++      phydata = 0;
++      for (i = 0; i < 16; ++i) {
++              phydata <<= 1;
++
++              if (bits[input_idx++] & MII_MDI)
++                      phydata |= 0x0001;
++      }
++
++#if (SMC_DEBUG > 2 )
++      printk("smc_read_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
++              phyaddr, phyreg, phydata);
++      smc_dump_mii_stream(bits, sizeof bits);
++#endif
++
++      return(phydata);
++}
++
++
++/*------------------------------------------------------------
++ . Writes a register to the MII Management serial interface
++ .-------------------------------------------------------------*/
++static void smc_write_phy_register(unsigned long ioaddr,
++      byte phyaddr, byte phyreg, word phydata)
++{
++      int oldBank;
++      int i;
++      word mask;
++      word mii_reg;
++      byte bits[65];
++      int clk_idx = 0;
++
++      // 32 consecutive ones on MDO to establish sync
++      for (i = 0; i < 32; ++i)
++              bits[clk_idx++] = MII_MDOE | MII_MDO;
++
++      // Start code <01>
++      bits[clk_idx++] = MII_MDOE;
++      bits[clk_idx++] = MII_MDOE | MII_MDO;
++
++      // Write command <01>
++      bits[clk_idx++] = MII_MDOE;
++      bits[clk_idx++] = MII_MDOE | MII_MDO;
++
++      // Output the PHY address, msb first
++      mask = (byte)0x10;
++      for (i = 0; i < 5; ++i) {
++              if (phyaddr & mask)
++                      bits[clk_idx++] = MII_MDOE | MII_MDO;
++              else
++                      bits[clk_idx++] = MII_MDOE;
++
++              // Shift to next lowest bit
++              mask >>= 1;
++      }
++
++      // Output the phy register number, msb first
++      mask = (byte)0x10;
++      for (i = 0; i < 5; ++i) {
++              if (phyreg & mask)
++                      bits[clk_idx++] = MII_MDOE | MII_MDO;
++              else
++                      bits[clk_idx++] = MII_MDOE;
++
++              // Shift to next lowest bit
++              mask >>= 1;
++      }
++
++      // Tristate and turnaround (2 bit times)
++      bits[clk_idx++] = 0;
++      bits[clk_idx++] = 0;
++
++      // Write out 16 bits of data, msb first
++      mask = 0x8000;
++      for (i = 0; i < 16; ++i) {
++              if (phydata & mask)
++                      bits[clk_idx++] = MII_MDOE | MII_MDO;
++              else
++                      bits[clk_idx++] = MII_MDOE;
++
++              // Shift to next lowest bit
++              mask >>= 1;
++      }
++
++      // Final clock bit (tristate)
++      bits[clk_idx++] = 0;
++
++      // Save the current bank
++      oldBank = SMC_CURRENT_BANK();
++
++      // Select bank 3
++      SMC_SELECT_BANK( 3 );
++
++      // Get the current MII register value
++      mii_reg = SMC_GET_MII();
++
++      // Turn off all MII Interface bits
++      mii_reg &= ~(MII_MDOE|MII_MCLK|MII_MDI|MII_MDO);
++
++      // Clock all cycles
++      for (i = 0; i < sizeof bits; ++i) {
++              // Clock Low - output data
++              SMC_SET_MII( mii_reg | bits[i] );
++              udelay(50);
++
++
++              // Clock Hi - input data
++              SMC_SET_MII( mii_reg | bits[i] | MII_MCLK );
++              udelay(50);
++              bits[i] |= SMC_GET_MII() & MII_MDI;
++      }
++
++      // Return to idle state
++      // Set clock to low, data to low, and output tristated
++      SMC_SET_MII( mii_reg );
++      udelay(50);
++
++      // Restore original bank select
++      SMC_SELECT_BANK( oldBank );
++
++#if (SMC_DEBUG > 2 )
++      printk("smc_write_phy_register(): phyaddr=%x,phyreg=%x,phydata=%x\n",
++              phyaddr, phyreg, phydata);
++      smc_dump_mii_stream(bits, sizeof bits);
++#endif
++}
++
++
++/*------------------------------------------------------------
++ . Finds and reports the PHY address
++ .-------------------------------------------------------------*/
++static int smc_detect_phy(struct net_device* dev)
++{
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++      unsigned long ioaddr = dev->base_addr;
++      word phy_id1;
++      word phy_id2;
++      int phyaddr;
++      int found = 0;
++
++      PRINTK3("%s:smc_detect_phy()\n", dev->name);
++
++      // Scan all 32 PHY addresses if necessary
++      for (phyaddr = 0; phyaddr < 32; ++phyaddr) {
++              // Read the PHY identifiers
++              phy_id1  = smc_read_phy_register(ioaddr, phyaddr, PHY_ID1_REG);
++              phy_id2  = smc_read_phy_register(ioaddr, phyaddr, PHY_ID2_REG);
++
++              PRINTK3("%s: phy_id1=%x, phy_id2=%x\n",
++                      dev->name, phy_id1, phy_id2);
++
++              // Make sure it is a valid identifier
++              if ((phy_id2 > 0x0000) && (phy_id2 < 0xffff) &&
++                  (phy_id1 > 0x0000) && (phy_id1 < 0xffff)) {
++                      if ((phy_id1 != 0x8000) && (phy_id2 != 0x8000)) {
++                              // Save the PHY's address
++                              lp->phyaddr = phyaddr;
++                              found = 1;
++                              break;
++                      }
++              }
++      }
++
++      if (!found) {
++              PRINTK("%s: No PHY found\n", dev->name);
++              return(0);
++      }
++
++      // Set the PHY type
++      if ( (phy_id1 == 0x0016) && ((phy_id2 & 0xFFF0) == 0xF840 ) ) {
++              lp->phytype = PHY_LAN83C183;
++              PRINTK("%s: PHY=LAN83C183 (LAN91C111 Internal)\n", dev->name);
++      }
++
++      if ( (phy_id1 == 0x0282) && ((phy_id2 & 0xFFF0) == 0x1C50) ) {
++              lp->phytype = PHY_LAN83C180;
++              PRINTK("%s: PHY=LAN83C180\n", dev->name);
++      }
++
++      return(1);
++}
++
++/*------------------------------------------------------------
++ . Waits the specified number of milliseconds - kernel friendly
++ .-------------------------------------------------------------*/
++static void smc_wait_ms(unsigned int ms)
++{
++
++      if (!in_interrupt()) {
++              set_current_state(TASK_UNINTERRUPTIBLE);
++              schedule_timeout(1 + ms * HZ / 1000);
++      } else {
++              set_current_state(TASK_INTERRUPTIBLE);
++              schedule_timeout(1 + ms * HZ / 1000);
++              set_current_state(TASK_RUNNING);
++      }
++}
++
++/*------------------------------------------------------------
++ . Sets the PHY to a configuration as determined by the user
++ .-------------------------------------------------------------*/
++static int smc_phy_fixed(struct net_device* dev)
++{
++      unsigned long ioaddr = dev->base_addr;
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++      byte phyaddr = lp->phyaddr;
++      word my_fixed_caps;
++      word cfg1;
++
++      PRINTK3("%s:smc_phy_fixed()\n", dev->name);
++
++      // Enter Link Disable state
++      cfg1 = smc_read_phy_register(ioaddr, phyaddr, PHY_CFG1_REG);
++      cfg1 |= PHY_CFG1_LNKDIS;
++      smc_write_phy_register(ioaddr, phyaddr, PHY_CFG1_REG, cfg1);
++
++      // Set our fixed capabilities
++      // Disable auto-negotiation
++      my_fixed_caps = 0;
++
++      if (lp->ctl_rfduplx)
++              my_fixed_caps |= PHY_CNTL_DPLX;
++
++      if (lp->ctl_rspeed == 100)
++              my_fixed_caps |= PHY_CNTL_SPEED;
++
++      // Write our capabilities to the phy control register
++      smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, my_fixed_caps);
++
++      // Re-Configure the Receive/Phy Control register
++      SMC_SET_RPC( lp->rpc_cur_mode );
++
++      // Success
++      return(1);
++}
++
++
++/*------------------------------------------------------------
++ . Configures the specified PHY using Autonegotiation. Calls
++ . smc_phy_fixed() if the user has requested a certain config.
++ .-------------------------------------------------------------*/
++static void smc_phy_configure(struct net_device* dev)
++{
++      unsigned long ioaddr = dev->base_addr;
++      struct smc_local *lp = (struct smc_local *)dev->priv;
++      int timeout;
++      byte phyaddr;
++      word my_phy_caps; // My PHY capabilities
++      word my_ad_caps; // My Advertised capabilities
++      word status;
++      int failed = 0;
++
++      PRINTK3("%s:smc_program_phy()\n", dev->name);
++
++      // Set the blocking flag
++      lp->autoneg_active = 1;
++
++      // Find the address and type of our phy
++      if (!smc_detect_phy(dev))
++              goto smc_phy_configure_exit;
++
++      // Get the detected phy address
++      phyaddr = lp->phyaddr;
++
++      // Reset the PHY, setting all other bits to zero
++      smc_write_phy_register(ioaddr, phyaddr, PHY_CNTL_REG, PHY_CNTL_RST);
++
++      // Wait for the reset to complete, or time out
++      timeout = 6; // Wait up to 3 seconds
++      while (timeout--) {
++              if (!(smc_read_phy_register(ioaddr, phyaddr, PHY_CNTL_REG)
++                  & PHY_CNTL_RST))
++                      // reset complete
++                      break;
++              smc_wait_ms(500); // wait 500 millisecs
++              if (signal_pending(current)) { // Exit anyway if signaled
++                      PRINTK2("%s:PHY reset interrupted by signal\n",
++                              dev->name);
++                      timeout = 0;
++                      break;
++              }
++      }
++
++      if (timeout < 1) {
++              printk("%s:PHY reset timed out\n", dev->name);
++              goto smc_phy_configure_exit;
++      }
++
++      // Read PHY Register 18, Status Output
++      lp->lastPhy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
++
++      // Enable PHY Interrupts (for register 18)
++      // Interrupts listed here are disabled
++      smc_write_phy_register(ioaddr, phyaddr, PHY_MASK_REG,
++              PHY_INT_LOSSSYNC | PHY_INT_CWRD | PHY_INT_SSD |
++              PHY_INT_ESD | PHY_INT_RPOL | PHY_INT_JAB |
++              PHY_INT_SPDDET | PHY_INT_DPLXDET);
++
++      /* Configure the Receive/Phy Control register */
++      SMC_SELECT_BANK( 0 );
++      SMC_SET_RPC( lp->rpc_cur_mode );
++
++      // Copy our capabilities from PHY_STAT_REG to PHY_AD_REG
++      my_phy_caps = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
++      my_ad_caps  = PHY_AD_CSMA; // I am CSMA capable
++
++      if (my_phy_caps & PHY_STAT_CAP_T4)
++              my_ad_caps |= PHY_AD_T4;
++
++      if (my_phy_caps & PHY_STAT_CAP_TXF)
++              my_ad_caps |= PHY_AD_TX_FDX;
++
++      if (my_phy_caps & PHY_STAT_CAP_TXH)
++              my_ad_caps |= PHY_AD_TX_HDX;
++
++      if (my_phy_caps & PHY_STAT_CAP_TF)
++              my_ad_caps |= PHY_AD_10_FDX;
++
++      if (my_phy_caps & PHY_STAT_CAP_TH)
++              my_ad_caps |= PHY_AD_10_HDX;
++
++      // Disable capabilities not selected by our user
++      if (lp->ctl_rspeed != 100)
++              my_ad_caps &= ~(PHY_AD_T4|PHY_AD_TX_FDX|PHY_AD_TX_HDX);
++
++      if (!lp->ctl_rfduplx)
++              my_ad_caps &= ~(PHY_AD_TX_FDX|PHY_AD_10_FDX);
++
++      // Update our Auto-Neg Advertisement Register
++      smc_write_phy_register(ioaddr, phyaddr, PHY_AD_REG, my_ad_caps);
++
++      // Read the register back.  Without this, it appears that when
++      // auto-negotiation is restarted, sometimes it isn't ready and
++      // the link does not come up.
++      status = smc_read_phy_register(ioaddr, phyaddr, PHY_AD_REG);
++
++      PRINTK2("%s:phy caps=%x\n", dev->name, my_phy_caps);
++      PRINTK2("%s:phy advertised caps=%x\n", dev->name, my_ad_caps);
++
++      // If the user requested no auto neg, then go set his request
++      if (!(lp->ctl_autoneg)) {
++              smc_phy_fixed(dev);
++              goto smc_phy_configure_exit;
++      }
++
++      // Restart auto-negotiation process in order to advertise my caps
++      smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
++              PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST );
++
++      // Wait for the auto-negotiation to complete.  This may take from
++      // 2 to 3 seconds.
++      // Wait for the reset to complete, or time out
++      timeout = 20; // Wait up to 10 seconds
++      while (timeout--) {
++              status = smc_read_phy_register(ioaddr, phyaddr, PHY_STAT_REG);
++              if (status & PHY_STAT_ANEG_ACK)
++                      // auto-negotiate complete
++                      break;
++
++              smc_wait_ms(500); // wait 500 millisecs
++              if (signal_pending(current)) { // Exit anyway if signaled
++                      printk(KERN_DEBUG
++                              "%s:PHY auto-negotiate interrupted by signal\n",
++                              dev->name);
++                      timeout = 0;
++                      break;
++              }
++
++              // Restart auto-negotiation if remote fault
++              if (status & PHY_STAT_REM_FLT) {
++                      PRINTK2("%s:PHY remote fault detected\n", dev->name);
++
++                      // Restart auto-negotiation
++                      PRINTK2("%s:PHY restarting auto-negotiation\n",
++                              dev->name);
++                      smc_write_phy_register( ioaddr, phyaddr, PHY_CNTL_REG,
++                              PHY_CNTL_ANEG_EN | PHY_CNTL_ANEG_RST |
++                              PHY_CNTL_SPEED | PHY_CNTL_DPLX);
++              }
++      }
++
++      if (timeout < 1) {
++              printk(KERN_DEBUG "%s:PHY auto-negotiate timed out\n",
++                      dev->name);
++              PRINTK2("%s:PHY auto-negotiate timed out\n", dev->name);
++              failed = 1;
++      }
++
++      // Fail if we detected an auto-negotiate remote fault
++      if (status & PHY_STAT_REM_FLT) {
++              printk(KERN_DEBUG "%s:PHY remote fault detected\n", dev->name);
++              PRINTK2("%s:PHY remote fault detected\n", dev->name);
++              failed = 1;
++      }
++
++      // The smc_phy_interrupt() routine will be called to update lastPhy18
++
++      // Set our sysctl parameters to match auto-negotiation results
++      if ( lp->lastPhy18 & PHY_INT_SPDDET ) {
++              PRINTK2("%s:PHY 100BaseT\n", dev->name);
++              lp->rpc_cur_mode |= RPC_SPEED;
++      } else {
++              PRINTK2("%s:PHY 10BaseT\n", dev->name);
++              lp->rpc_cur_mode &= ~RPC_SPEED;
++      }
++
++      if ( lp->lastPhy18 & PHY_INT_DPLXDET ) {
++              PRINTK2("%s:PHY Full Duplex\n", dev->name);
++              lp->rpc_cur_mode |= RPC_DPLX;
++      } else {
++              PRINTK2("%s:PHY Half Duplex\n", dev->name);
++              lp->rpc_cur_mode &= ~RPC_DPLX;
++      }
++
++      // Re-Configure the Receive/Phy Control register
++      SMC_SET_RPC( lp->rpc_cur_mode );
++
++smc_phy_configure_exit:
++      // Exit auto-negotiation
++      lp->autoneg_active = 0;
++}
++
++
++
++/*************************************************************************
++ . smc_phy_interrupt
++ .
++ . Purpose:  Handle interrupts relating to PHY register 18. This is
++ .  called from the "hard" interrupt handler.
++ .
++ ************************************************************************/
++static void smc_phy_interrupt(struct net_device* dev)
++{
++      unsigned long ioaddr    = dev->base_addr;
++      struct smc_local *lp    = (struct smc_local *)dev->priv;
++      byte phyaddr = lp->phyaddr;
++      word phy18;
++
++      PRINTK2("%s: smc_phy_interrupt\n", dev->name);
++
++      for(;;) {
++              // Read PHY Register 18, Status Output
++              phy18 = smc_read_phy_register(ioaddr, phyaddr, PHY_INT_REG);
++
++              // Exit if not more changes
++              if (phy18 == lp->lastPhy18)
++                      break;
++
++#if (SMC_DEBUG > 1 )
++              PRINTK2("%s:     phy18=0x%x\n", dev->name, phy18);
++              PRINTK2("%s: lastPhy18=0x%x\n", dev->name, lp->lastPhy18);
++
++              // Handle events
++              if ((phy18 & PHY_INT_LNKFAIL) !=
++                              (lp->lastPhy18 & PHY_INT_LNKFAIL))
++                      PRINTK2("%s: PHY Link Fail=%x\n", dev->name,
++                                      phy18 & PHY_INT_LNKFAIL);
++
++              if ((phy18 & PHY_INT_LOSSSYNC) !=
++                              (lp->lastPhy18 & PHY_INT_LOSSSYNC))
++                      PRINTK2("%s: PHY LOSS SYNC=%x\n", dev->name,
++                                      phy18 & PHY_INT_LOSSSYNC);
++
++              if ((phy18 & PHY_INT_CWRD) != (lp->lastPhy18 & PHY_INT_CWRD))
++                      PRINTK2("%s: PHY INVALID 4B5B code=%x\n", dev->name,
++                                      phy18 & PHY_INT_CWRD);
++
++              if ((phy18 & PHY_INT_SSD) != (lp->lastPhy18 & PHY_INT_SSD))
++                      PRINTK2("%s: PHY No Start Of Stream=%x\n", dev->name,
++                                      phy18 & PHY_INT_SSD);
++
++              if ((phy18 & PHY_INT_ESD) != (lp->lastPhy18 & PHY_INT_ESD))
++
++                      PRINTK2("%s: PHY No End Of Stream=%x\n", dev->name,
++                                      phy18 & PHY_INT_ESD);
++
++              if ((phy18 & PHY_INT_RPOL) != (lp->lastPhy18 & PHY_INT_RPOL))
++                      PRINTK2("%s: PHY Reverse Polarity Detected=%x\n",
++                                      dev->name, phy18 & PHY_INT_RPOL);
++
++              if ((phy18 & PHY_INT_JAB) != (lp->lastPhy18 & PHY_INT_JAB))
++                      PRINTK2("%s: PHY Jabber Detected=%x\n", dev->name,
++                                      phy18 & PHY_INT_JAB);
++
++              if ((phy18 & PHY_INT_SPDDET) !=
++                              (lp->lastPhy18 & PHY_INT_SPDDET))
++                      PRINTK2("%s: PHY Speed Detect=%x\n", dev->name,
++                                      phy18 & PHY_INT_SPDDET);
++
++              if ((phy18 & PHY_INT_DPLXDET) !=
++                              (lp->lastPhy18 & PHY_INT_DPLXDET))
++                      PRINTK2("%s: PHY Duplex Detect=%x\n", dev->name,
++                                      phy18 & PHY_INT_DPLXDET);
++#endif
++              // Update the last phy 18 variable
++              lp->lastPhy18 = phy18;
++      }
++}
+diff -Narup linux-2.4.31-orig/drivers/net/smc91111.h linux-2.4.31/drivers/net/smc91111.h
+--- linux-2.4.31-orig/drivers/net/smc91111.h   1969-12-31 16:00:00.000000000 -0800
++++ linux-2.4.31/drivers/net/smc91111.h        2005-08-08 16:03:33.000000000 -0700
+@@ -0,0 +1,712 @@
++/*------------------------------------------------------------------------
++ . smc91111.h - macros for the LAN91C111 Ethernet Driver
++ .
++ . Copyright (C) 2001 Standard Microsystems Corporation (SMSC)
++ .       Developed by Simple Network Magic Corporation (SNMC)
++ . Copyright (C) 1996 by Erik Stahlman (ES)
++ .
++ . This program is free software; you can redistribute it and/or modify
++ . it under the terms of the GNU General Public License as published by
++ . the Free Software Foundation; either version 2 of the License, or
++ . (at your option) any later version.
++ .
++ . This program is distributed in the hope that it will be useful,
++ . but WITHOUT ANY WARRANTY; without even the implied warranty of
++ . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ . GNU General Public License for more details.
++ .
++ . You should have received a copy of the GNU General Public License
++ . along with this program; if not, write to the Free Software
++ . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ .
++ . This file contains register information and access macros for
++ . the LAN91C111 single chip ethernet controller.  It is a modified
++ . version of the smc9194.h file.
++ .
++ . Information contained in this file was obtained from the LAN91C111
++ . manual from SMC.  To get a copy, if you really want one, you can find
++ . information under www.smsc.com.
++ .
++ . Authors
++ .    Erik Stahlman                           ( erik@vt.edu )
++ .    Daris A Nevil                           ( dnevil@snmc.com )
++ .
++ . History
++ . 03/16/01           Daris A Nevil   Modified for use with LAN91C111 device
++ .
++ ---------------------------------------------------------------------------*/
++#ifndef _SMC91111_H_
++#define _SMC91111_H_
++
++/* I want some simple types */
++
++typedef unsigned char                 byte;
++typedef unsigned short                        word;
++typedef unsigned long int             dword;
++
++
++/*
++ . Do you want to use 8 bit xfers?  This should work on all chips, as the
++ . chipset is designed to accommodate them, although some hardware engineers
++ . do not connect byte enables so 8 bit xfers can not be used.
++*/
++#ifdef CONFIG_SMC91111_USE_8_BIT
++#define SMC_inb(port)         inb(port)
++#define SMC_insb(port,buf,ns) insb((port),(buf),(ns))
++#define SMC_outb(val,port)    outb((val),(port))
++#define SMC_outsb(port,buf,ns)        outsb((port),(buf),(ns))
++#endif /* CONFIG_SMC91111_USE_8_BIT */
++
++/* Define 16 bit xfers. */
++#ifdef CONFIG_SMC91111_BYTE_SWAP
++#define SMC_inw(port)         swab16(inw(port))
++#define SMC_insw(port,buf,ns)                                                 \
++      do {                                                            \
++              unsigned long __port = (port);                          \
++              word *__buf = (word *)(buf);                            \
++              int __ns = (ns);                                        \
++              insw(__port,__buf,__ns);                                \
++              while (__ns > 0) {                                      \
++                      *__buf = swab16(*__buf);                        \
++                      __buf++;                                        \
++                      __ns--;                                         \
++              }                                                       \
++      } while (0)
++#define SMC_outw(val,port)    outw(swab16(val),(port))
++#define SMC_outsw(port,buf,ns)                                                \
++      do {                                                            \
++              unsigned long __port = (port);                          \
++              word *__buf = (word *)(buf);                            \
++              int __ns = (ns);                                        \
++              while (__ns > 0) {                                      \
++                      /* Believe it or not, the swab isn't needed. */ \
++                      outw( /* swab16 */ (*__buf++), __port);         \
++                      __ns--;                                         \
++              }                                                       \
++      } while (0)
++#else /* CONFIG_SMC91111_BYTE_SWAP is not defined */
++#define SMC_inw(port)         inw(port)
++#define SMC_insw(port,buf,ns) insw((port),(buf),(ns))
++#define SMC_outw(val,port)    outw((val),(port))
++#define SMC_outsw(port,buf,ns)        outsw((port),(buf),(ns))
++#endif /* CONFIG_SMC91111_BYTE_SWAP */
++
++/*
++ . Do you want to use 32 bit xfers?  This should work on all chips, as the
++ . chipset is designed to accommodate them, although some hardware engineers
++ . do not connect all 32 data bits so 32 bit xfers can not be used.
++*/
++#ifdef CONFIG_SMC91111_USE_32_BIT
++#ifdef CONFIG_SMC91111_BYTE_SWAP
++#define SMC_inl(port)         swab32(inl(port))
++#define SMC_insl(port,buf,ns)                                                 \
++      do {                                                            \
++              unsigned long __port = (port);                          \
++              dword *__buf = (dword *)(buf);                          \
++              int __ns = (ns);                                        \
++              insl(__port,__buf,__ns);                                \
++              while (__ns > 0) {                                      \
++                      *__buf = swab32(*__buf);                        \
++                      __buf++;                                        \
++                      __ns--;                                         \
++              }                                                       \
++      } while (0)
++#define SMC_outl(val,port)    outl(swab32(val),(port))
++#define SMC_outsl(port,buf,ns)                                                \
++      do {                                                            \
++              unsigned long __port = (port);                          \
++              dword *__buf = (dword *)(buf);                          \
++              int __ns = (ns);                                        \
++              while (__ns > 0) {                                      \
++                      /* Believe it or not, the swab isn't needed. */ \
++                      outl( /* swab32 */ (*__buf++), __port);         \
++                      __ns--;                                         \
++              }                                                       \
++      } while (0)
++#else /* CONFIG_SMC91111_BYTE_SWAP is not defined */
++#define SMC_inl(port)         inl(port)
++#define SMC_insl(port,buf,ns) insl((port),(buf),(ns))
++#define SMC_outl(val,port)    outl((val),(port))
++#define SMC_outsl(port,buf,ns)        outsl((port),(buf),(ns))
++#endif /* CONFIG_SMC91111_BYTE_SWAP */
++#endif /* CONFIG_SMC91111_USE_32_BIT */
++
++
++/* Because of bank switching, the LAN91xxx uses only 16 I/O ports */
++
++#define SMC_IO_EXTENT 16
++
++
++/*---------------------------------------------------------------
++ .
++ . A description of the SMSC registers is probably in order here,
++ . although for details, the SMC datasheet is invaluable.
++ .
++ . Basically, the chip has 4 banks of registers ( 0 to 3 ), which
++ . are accessed by writing a number into the BANK_SELECT register
++ . ( I also use a SMC_SELECT_BANK macro for this ).
++ .
++ . The banks are configured so that for most purposes, bank 2 is all
++ . that is needed for simple run time tasks.
++ -----------------------------------------------------------------------*/
++
++/*
++ . Bank Select Register:
++ .
++ .            yyyy yyyy 0000 00xx
++ .            xx              = bank number
++ .            yyyy yyyy       = 0x33, for identification purposes.
++*/
++#define BANK_SELECT           14
++
++// Transmit Control Register
++/* BANK 0  */
++#define TCR_REG       0x0000  // transmit control register
++#define TCR_ENABLE    0x0001  // When 1 we can transmit
++#define TCR_LOOP      0x0002  // Controls output pin LBK
++#define TCR_FORCOL    0x0004  // When 1 will force a collision
++#define TCR_PAD_EN    0x0080  // When 1 will pad tx frames < 64 bytes w/0
++#define TCR_NOCRC     0x0100  // When 1 will not append CRC to tx frames
++#define TCR_MON_CSN   0x0400  // When 1 tx monitors carrier
++#define TCR_FDUPLX            0x0800  // When 1 enables full duplex operation
++#define TCR_STP_SQET  0x1000  // When 1 stops tx if Signal Quality Error
++#define TCR_EPH_LOOP  0x2000  // When 1 enables EPH block loopback
++#define TCR_SWFDUP    0x8000  // When 1 enables Switched Full Duplex mode
++
++#define TCR_CLEAR     0       /* do NOTHING */
++/* the default settings for the TCR register : */
++/* QUESTION: do I want to enable padding of short packets ? */
++#define TCR_DEFAULT   TCR_ENABLE
++
++
++// EPH Status Register
++/* BANK 0  */
++#define EPH_STATUS_REG        0x0002
++#define ES_TX_SUC     0x0001  // Last TX was successful
++#define ES_SNGL_COL   0x0002  // Single collision detected for last tx
++#define ES_MUL_COL    0x0004  // Multiple collisions detected for last tx
++#define ES_LTX_MULT   0x0008  // Last tx was a multicast
++#define ES_16COL      0x0010  // 16 Collisions Reached
++#define ES_SQET               0x0020  // Signal Quality Error Test
++#define ES_LTXBRD     0x0040  // Last tx was a broadcast
++#define ES_TXDEFR     0x0080  // Transmit Deferred
++#define ES_LATCOL     0x0200  // Late collision detected on last tx
++#define ES_LOSTCARR   0x0400  // Lost Carrier Sense
++#define ES_EXC_DEF    0x0800  // Excessive Deferral
++#define ES_CTR_ROL    0x1000  // Counter Roll Over indication
++#define ES_LINK_OK    0x4000  // Driven by inverted value of nLNK pin
++#define ES_TXUNRN     0x8000  // Tx Underrun
++
++
++// Receive Control Register
++/* BANK 0  */
++#define RCR_REG               0x0004
++#define RCR_RX_ABORT  0x0001  // Set if a rx frame was aborted
++#define RCR_PRMS      0x0002  // Enable promiscuous mode
++#define RCR_ALMUL     0x0004  // When set accepts all multicast frames
++#define RCR_RXEN      0x0100  // IFF this is set, we can receive packets
++#define RCR_STRIP_CRC 0x0200  // When set strips CRC from rx packets
++#define RCR_ABORT_ENB 0x0200  // When set will abort rx on collision
++#define RCR_FILT_CAR  0x0400  // When set filters leading 12 bit s of carrier
++#define RCR_SOFTRST   0x8000  // resets the chip
++
++/* the normal settings for the RCR register : */
++#define RCR_DEFAULT   (RCR_STRIP_CRC | RCR_RXEN)
++#define RCR_CLEAR     0x0     // set it to a base state
++
++// Counter Register
++/* BANK 0  */
++#define COUNTER_REG   0x0006
++
++// Memory Information Register
++/* BANK 0  */
++#define MIR_REG               0x0008
++
++// Receive/Phy Control Register
++/* BANK 0  */
++#define RPC_REG               0x000A
++#define RPC_SPEED     0x2000  // When 1 PHY is in 100Mbps mode.
++#define RPC_DPLX      0x1000  // When 1 PHY is in Full-Duplex Mode
++#define RPC_ANEG      0x0800  // When 1 PHY is in Auto-Negotiate Mode
++#define RPC_LSXA_SHFT 5       // Bits to shift LS2A,LS1A,LS0A to lsb
++#define RPC_LSXB_SHFT 2       // Bits to get LS2B,LS1B,LS0B to lsb
++#define RPC_LED_100_10        (0x00)  // LED = 100Mbps OR's with 10Mbps link detect
++#define RPC_LED_RES   (0x01)  // LED = Reserved
++#define RPC_LED_10    (0x02)  // LED = 10Mbps link detect
++#define RPC_LED_FD    (0x03)  // LED = Full Duplex Mode
++#define RPC_LED_TX_RX (0x04)  // LED = TX or RX packet occurred
++#define RPC_LED_100   (0x05)  // LED = 100Mbps link dectect
++#define RPC_LED_TX    (0x06)  // LED = TX packet occurred
++#define RPC_LED_RX    (0x07)  // LED = RX packet occurred
++#define RPC_DEFAULT (RPC_ANEG | (RPC_LED_100 << RPC_LSXA_SHFT) | (RPC_LED_FD << RPC_LSXB_SHFT) | RPC_SPEED | RPC_DPLX)
++
++/* Bank 0 0x000C is reserved */
++
++// Bank Select Register
++/* All Banks */
++#define BSR_REG       0x000E
++
++
++// Configuration Reg
++/* BANK 1 */
++#define CONFIG_REG    0x0000
++#define CONFIG_EXT_PHY        0x0200  // 1=external MII, 0=internal Phy
++#define CONFIG_GPCNTRL        0x0400  // Inverse value drives pin nCNTRL
++#define CONFIG_NO_WAIT        0x1000  // When 1 no extra wait states on ISA bus
++#define CONFIG_EPH_POWER_EN 0x8000 // When 0 EPH is placed into low power mode.
++
++// Default is powered-up, Internal Phy, Wait States, and pin nCNTRL=low
++#define CONFIG_DEFAULT        (CONFIG_EPH_POWER_EN)
++
++
++// Base Address Register
++/* BANK 1 */
++#define BASE_REG      0x0002
++
++
++// Individual Address Registers
++/* BANK 1 */
++#define ADDR0_REG     0x0004
++#define ADDR1_REG     0x0006
++#define ADDR2_REG     0x0008
++
++
++// General Purpose Register
++/* BANK 1 */
++#define GP_REG                0x000A
++
++
++// Control Register
++/* BANK 1 */
++#define CTL_REG               0x000C
++#define CTL_RCV_BAD   0x4000 // When 1 bad CRC packets are received
++#define CTL_AUTO_RELEASE 0x0800 // When 1 tx pages are released automatically
++#define CTL_LE_ENABLE 0x0080 // When 1 enables Link Error interrupt
++#define CTL_CR_ENABLE 0x0040 // When 1 enables Counter Rollover interrupt
++#define CTL_TE_ENABLE 0x0020 // When 1 enables Transmit Error interrupt
++#define CTL_EEPROM_SELECT 0x0004 // Controls EEPROM reload & store
++#define CTL_RELOAD    0x0002 // When set reads EEPROM into registers
++#define CTL_STORE     0x0001 // When set stores registers into EEPROM
++
++
++// MMU Command Register
++/* BANK 2 */
++#define MMU_CMD_REG   0x0000
++#define MC_BUSY               1       // When 1 the last release has not completed
++#define MC_NOP                (0<<5)  // No Op
++#define MC_ALLOC      (1<<5)  // OR with number of 256 byte packets
++#define MC_RESET      (2<<5)  // Reset MMU to initial state
++#define MC_REMOVE     (3<<5)  // Remove the current rx packet
++#define MC_RELEASE    (4<<5)  // Remove and release the current rx packet
++#define MC_FREEPKT    (5<<5)  // Release packet in PNR register
++#define MC_ENQUEUE    (6<<5)  // Enqueue the packet for transmit
++#define MC_RSTTXFIFO  (7<<5)  // Reset the TX FIFOs
++
++
++// Packet Number Register
++/* BANK 2 */
++#define PN_REG                0x0002
++
++
++// Allocation Result Register
++/* BANK 2 */
++#define AR_REG                0x0003
++#define AR_FAILED     0x80    // Alocation Failed
++
++
++// RX FIFO Ports Register
++/* BANK 2 */
++#define RXFIFO_REG    0x0004  // Must be read as a word
++#define RXFIFO_REMPTY 0x8000  // RX FIFO Empty
++
++
++// TX FIFO Ports Register
++/* BANK 2 */
++#define TXFIFO_REG    RXFIFO_REG      // Must be read as a word
++#define TXFIFO_TEMPTY 0x80    // TX FIFO Empty
++
++
++// Pointer Register
++/* BANK 2 */
++#define PTR_REG               0x0006
++#define PTR_RCV               0x8000 // 1=Receive area, 0=Transmit area
++#define PTR_AUTOINC   0x4000 // Auto increment the pointer on each access
++#define PTR_READ      0x2000 // When 1 the operation is a read
++
++
++// Data Register
++/* BANK 2 */
++#define DATA_REG      0x0008
++
++
++// Interrupt Status/Acknowledge Register
++/* BANK 2 */
++#define INT_REG               0x000C
++
++
++// Interrupt Mask Register
++/* BANK 2 */
++#define IM_REG                0x000D
++#define IM_MDINT      0x80 // PHY MI Register 18 Interrupt
++#define IM_ERCV_INT   0x40 // Early Receive Interrupt
++#define IM_EPH_INT    0x20 // Set by Etheret Protocol Handler section
++#define IM_RX_OVRN_INT        0x10 // Set by Receiver Overruns
++#define IM_ALLOC_INT  0x08 // Set when allocation request is completed
++#define IM_TX_EMPTY_INT       0x04 // Set if the TX FIFO goes empty
++#define IM_TX_INT     0x02 // Transmit Interrrupt
++#define IM_RCV_INT    0x01 // Receive Interrupt
++
++
++// Multicast Table Registers
++/* BANK 3 */
++#define MCAST_REG1    0x0000
++#define MCAST_REG2    0x0002
++#define MCAST_REG3    0x0004
++#define MCAST_REG4    0x0006
++
++
++// Management Interface Register (MII)
++/* BANK 3 */
++#define MII_REG               0x0008
++#define MII_MSK_CRS100        0x4000 // Disables CRS100 detection during tx half dup
++#define MII_MDOE      0x0008 // MII Output Enable
++#define MII_MCLK      0x0004 // MII Clock, pin MDCLK
++#define MII_MDI               0x0002 // MII Input, pin MDI
++#define MII_MDO               0x0001 // MII Output, pin MDO
++
++
++// Revision Register
++/* BANK 3 */
++#define REV_REG               0x000A /* ( hi: chip id   low: rev # ) */
++
++
++// Early RCV Register
++/* BANK 3 */
++/* this is NOT on SMC9192 */
++#define ERCV_REG      0x000C
++#define ERCV_RCV_DISCRD       0x0080 // When 1 discards a packet being received
++#define ERCV_THRESHOLD        0x001F // ERCV Threshold Mask
++
++// External Register
++/* BANK 7 */
++#define EXT_REG               0x0000
++
++
++#define CHIP_9192     3
++#define CHIP_9194     4
++#define CHIP_9195     5
++#define CHIP_9196     6
++#define CHIP_91100    7
++#define CHIP_91100FD  8
++#define CHIP_91111FD  9
++
++static const char * chip_ids[ 15 ] =  {
++      NULL, NULL, NULL,
++      /* 3 */ "SMC91C90/91C92",
++      /* 4 */ "SMC91C94",
++      /* 5 */ "SMC91C95",
++      /* 6 */ "SMC91C96",
++      /* 7 */ "SMC91C100",
++      /* 8 */ "SMC91C100FD",
++      /* 9 */ "SMC91C11xFD",
++      NULL, NULL,
++      NULL, NULL, NULL};
++
++/*
++ . Transmit status bits
++*/
++#define TS_SUCCESS 0x0001
++#define TS_LOSTCAR 0x0400
++#define TS_LATCOL  0x0200
++#define TS_16COL   0x0010
++
++/*
++ . Receive status bits
++*/
++#define RS_ALGNERR    0x8000
++#define RS_BRODCAST   0x4000
++#define RS_BADCRC     0x2000
++#define RS_ODDFRAME   0x1000  // bug: the LAN91C111 never sets this on receive
++#define RS_TOOLONG    0x0800
++#define RS_TOOSHORT   0x0400
++#define RS_MULTICAST  0x0001
++#define RS_ERRORS     (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
++
++
++// PHY Types
++enum {
++      PHY_LAN83C183 = 1,      // LAN91C111 Internal PHY
++      PHY_LAN83C180
++};
++
++
++// PHY Register Addresses (LAN91C111 Internal PHY)
++
++// PHY Control Register
++#define PHY_CNTL_REG          0x00
++#define PHY_CNTL_RST          0x8000  // 1=PHY Reset
++#define PHY_CNTL_LPBK         0x4000  // 1=PHY Loopback
++#define PHY_CNTL_SPEED                0x2000  // 1=100Mbps, 0=10Mpbs
++#define PHY_CNTL_ANEG_EN      0x1000 // 1=Enable Auto negotiation
++#define PHY_CNTL_PDN          0x0800  // 1=PHY Power Down mode
++#define PHY_CNTL_MII_DIS      0x0400  // 1=MII 4 bit interface disabled
++#define PHY_CNTL_ANEG_RST     0x0200 // 1=Reset Auto negotiate
++#define PHY_CNTL_DPLX         0x0100  // 1=Full Duplex, 0=Half Duplex
++#define PHY_CNTL_COLTST               0x0080  // 1= MII Colision Test
++
++// PHY Status Register
++#define PHY_STAT_REG          0x01
++#define PHY_STAT_CAP_T4               0x8000  // 1=100Base-T4 capable
++#define PHY_STAT_CAP_TXF      0x4000  // 1=100Base-X full duplex capable
++#define PHY_STAT_CAP_TXH      0x2000  // 1=100Base-X half duplex capable
++#define PHY_STAT_CAP_TF               0x1000  // 1=10Mbps full duplex capable
++#define PHY_STAT_CAP_TH               0x0800  // 1=10Mbps half duplex capable
++#define PHY_STAT_CAP_SUPR     0x0040  // 1=recv mgmt frames with not preamble
++#define PHY_STAT_ANEG_ACK     0x0020  // 1=ANEG has completed
++#define PHY_STAT_REM_FLT      0x0010  // 1=Remote Fault detected
++#define PHY_STAT_CAP_ANEG     0x0008  // 1=Auto negotiate capable
++#define PHY_STAT_LINK         0x0004  // 1=valid link
++#define PHY_STAT_JAB          0x0002  // 1=10Mbps jabber condition
++#define PHY_STAT_EXREG                0x0001  // 1=extended registers implemented
++
++// PHY Identifier Registers
++#define PHY_ID1_REG           0x02    // PHY Identifier 1
++#define PHY_ID2_REG           0x03    // PHY Identifier 2
++
++// PHY Auto-Negotiation Advertisement Register
++#define PHY_AD_REG            0x04
++#define PHY_AD_NP             0x8000  // 1=PHY requests exchange of Next Page
++#define PHY_AD_ACK            0x4000  // 1=got link code word from remote
++#define PHY_AD_RF             0x2000  // 1=advertise remote fault
++#define PHY_AD_T4             0x0200  // 1=PHY is capable of 100Base-T4
++#define PHY_AD_TX_FDX         0x0100  // 1=PHY is capable of 100Base-TX FDPLX
++#define PHY_AD_TX_HDX         0x0080  // 1=PHY is capable of 100Base-TX HDPLX
++#define PHY_AD_10_FDX         0x0040  // 1=PHY is capable of 10Base-T FDPLX
++#define PHY_AD_10_HDX         0x0020  // 1=PHY is capable of 10Base-T HDPLX
++#define PHY_AD_CSMA           0x0001  // 1=PHY is capable of 802.3 CMSA
++
++// PHY Auto-negotiation Remote End Capability Register
++#define PHY_RMT_REG           0x05
++// Uses same bit definitions as PHY_AD_REG
++
++// PHY Configuration Register 1
++#define PHY_CFG1_REG          0x10
++#define PHY_CFG1_LNKDIS               0x8000  // 1=Rx Link Detect Function disabled
++#define PHY_CFG1_XMTDIS               0x4000  // 1=TP Transmitter Disabled
++#define PHY_CFG1_XMTPDN               0x2000  // 1=TP Transmitter Powered Down
++#define PHY_CFG1_BYPSCR               0x0400  // 1=Bypass scrambler/descrambler
++#define PHY_CFG1_UNSCDS               0x0200  // 1=Unscramble Idle Reception Disable
++#define PHY_CFG1_EQLZR                0x0100  // 1=Rx Equalizer Disabled
++#define PHY_CFG1_CABLE                0x0080  // 1=STP(150ohm), 0=UTP(100ohm)
++#define PHY_CFG1_RLVL0                0x0040  // 1=Rx Squelch level reduced by 4.5db
++#define PHY_CFG1_TLVL_SHIFT   2       // Transmit Output Level Adjust
++#define PHY_CFG1_TLVL_MASK    0x003C
++#define PHY_CFG1_TRF_MASK     0x0003  // Transmitter Rise/Fall time
++
++
++// PHY Configuration Register 2
++#define PHY_CFG2_REG          0x11
++#define PHY_CFG2_APOLDIS      0x0020  // 1=Auto Polarity Correction disabled
++#define PHY_CFG2_JABDIS               0x0010  // 1=Jabber disabled
++#define PHY_CFG2_MREG         0x0008  // 1=Multiple register access (MII mgt)
++#define PHY_CFG2_INTMDIO      0x0004  // 1=Interrupt signaled with MDIO pulseo
++
++// PHY Status Output (and Interrupt status) Register
++#define PHY_INT_REG           0x12    // Status Output (Interrupt Status)
++#define PHY_INT_INT           0x8000  // 1=bits have changed since last read
++#define PHY_INT_LNKFAIL               0x4000  // 1=Link Not detected
++#define PHY_INT_LOSSSYNC      0x2000  // 1=Descrambler has lost sync
++#define PHY_INT_CWRD          0x1000  // 1=Invalid 4B5B code detected on rx
++#define PHY_INT_SSD           0x0800  // 1=No Start Of Stream detected on rx
++#define PHY_INT_ESD           0x0400  // 1=No End Of Stream detected on rx
++#define PHY_INT_RPOL          0x0200  // 1=Reverse Polarity detected
++#define PHY_INT_JAB           0x0100  // 1=Jabber detected
++#define PHY_INT_SPDDET                0x0080  // 1=100Base-TX mode, 0=10Base-T mode
++#define PHY_INT_DPLXDET               0x0040  // 1=Device in Full Duplex
++
++// PHY Interrupt/Status Mask Register
++#define PHY_MASK_REG          0x13    // Interrupt Mask
++// Uses the same bit definitions as PHY_INT_REG
++
++
++
++/*-------------------------------------------------------------------------
++ .  I define some macros to make it easier to do somewhat common
++ . or slightly complicated, repeated tasks.
++ --------------------------------------------------------------------------*/
++
++/* select a register bank, 0 to 3  */
++
++#define SMC_SELECT_BANK(x)  { SMC_outw( x, ioaddr + BANK_SELECT ); }
++#define SMC_CURRENT_BANK()  SMC_inw( ioaddr + BANK_SELECT )
++
++/* this enables an interrupt in the interrupt mask register */
++#define SMC_ENABLE_INT(x) {\
++              unsigned char mask;\
++              SMC_SELECT_BANK(2);\
++              mask = SMC_GET_INT_MASK();\
++              mask |= (x);\
++              SMC_SET_INT_MASK(mask); \
++}
++
++/* this disables an interrupt from the interrupt mask register */
++
++#define SMC_DISABLE_INT(x) {\
++              unsigned char mask;\
++              SMC_SELECT_BANK(2);\
++              mask = SMC_GET_INT_MASK();\
++              mask &= ~(x);\
++              SMC_SET_INT_MASK(mask); \
++}
++
++/* Note: the following macros do *not* select the bank. */
++#if USE_8_BIT
++#define SMC_GET_PN()          SMC_inb( ioaddr + PN_REG )
++#define SMC_SET_PN(x)         SMC_outb( (x), ioaddr + PN_REG )
++#define SMC_GET_AR()          SMC_inb( ioaddr + AR_REG )
++#define SMC_GET_INT()         SMC_inb( ioaddr + INT_REG )
++#define SMC_ACK_INT(x)                SMC_outb( (x), ioaddr + INT_REG )
++#define SMC_GET_INT_MASK()    SMC_inb( ioaddr + IM_REG )
++#define SMC_SET_INT_MASK(x)   SMC_outb( (x), ioaddr + IM_REG )
++#else
++#define SMC_GET_PN()          (SMC_inw( ioaddr + PN_REG ) & 0xFF)
++#define SMC_SET_PN(x)         SMC_outw( (x), ioaddr + PN_REG )
++#define SMC_GET_AR()          (SMC_inw( ioaddr + PN_REG ) >> 8)
++#define SMC_GET_INT()         (SMC_inw( ioaddr + INT_REG ) & 0xFF)
++#define SMC_ACK_INT(x)                SMC_outw( (SMC_GET_INT_MASK() << 8) | (x), \
++                                        ioaddr + INT_REG )
++#define SMC_GET_INT_MASK()    (SMC_inw( ioaddr + INT_REG ) >> 8)
++#define SMC_SET_INT_MASK(x)   SMC_outw( (x) << 8, ioaddr + INT_REG )
++#endif
++
++#define SMC_GET_BASE()                SMC_inw( ioaddr + BASE_REG)
++#define SMC_SET_BASE(x)               SMC_outw( (x), ioaddr + BASE_REG)
++#define SMC_GET_CONFIG()      SMC_inw( ioaddr + CONFIG_REG)
++#define SMC_SET_CONFIG(x)     SMC_outw( (x), ioaddr + CONFIG_REG)
++#define SMC_GET_COUNTER()     SMC_inw( ioaddr + COUNTER_REG)
++#define SMC_SET_COUNTER(x)    SMC_outw( (x), ioaddr + COUNTER_REG)
++#define SMC_GET_CTL()         SMC_inw( ioaddr + CTL_REG)
++#define SMC_SET_CTL(x)                SMC_outw( (x), ioaddr + CTL_REG)
++#define SMC_GET_MII()         SMC_inw( ioaddr + MII_REG)
++#define SMC_SET_MII(x)                SMC_outw( (x), ioaddr + MII_REG)
++#define SMC_GET_MIR()         SMC_inw( ioaddr + MIR_REG)
++#define SMC_SET_MIR(x)                SMC_outw( (x), ioaddr + MIR_REG)
++#define SMC_GET_MMU_CMD()     SMC_inw( ioaddr + MMU_CMD_REG)
++#define SMC_SET_MMU_CMD(x)    SMC_outw( (x), ioaddr + MMU_CMD_REG)
++#define SMC_GET_PTR()         SMC_inw( ioaddr + PTR_REG)
++#define SMC_SET_PTR(x)                SMC_outw( (x), ioaddr + PTR_REG)
++#define SMC_GET_RCR()         SMC_inw( ioaddr + RCR_REG)
++#define SMC_SET_RCR(x)                SMC_outw( (x), ioaddr + RCR_REG)
++#define SMC_GET_REV()         SMC_inw( ioaddr + REV_REG)
++#define SMC_SET_REV(x)                SMC_outw( (x), ioaddr + REV_REG)
++#define SMC_GET_RPC()         SMC_inw( ioaddr + RPC_REG)
++#define SMC_SET_RPC(x)                SMC_outw( (x), ioaddr + RPC_REG)
++#define SMC_GET_RXFIFO()      SMC_inw( ioaddr + RXFIFO_REG)
++#define SMC_SET_RXFIFO(x)     SMC_outw( (x), ioaddr + RXFIFO_REG)
++#define SMC_GET_TCR()         SMC_inw( ioaddr + TCR_REG)
++#define SMC_SET_TCR(x)                SMC_outw( (x), ioaddr + TCR_REG)
++
++#define SMC_CLEAR_MCAST()     {\
++              SMC_outw( 0, ioaddr + MCAST_REG1); \
++              SMC_outw( 0, ioaddr + MCAST_REG2); \
++              SMC_outw( 0, ioaddr + MCAST_REG3); \
++              SMC_outw( 0, ioaddr + MCAST_REG4); \
++}
++#define SMC_SET_MCAST(x) {\
++              int i;\
++              word w;\
++              unsigned char *mt = (x);\
++              for ( i = 0; i < 8; i += 2 ) {\
++                      w = mt[i] | (mt[i + 1] << 8);\
++                      SMC_outw( w, ioaddr + MCAST_REG1 + i );\
++              }\
++}
++
++
++/*----------------------------------------------------------------------
++ . Define the interrupts that I want to receive from the card
++ .
++ . I want:
++ .  IM_EPH_INT, for nasty errors
++ .  IM_RCV_INT, for happy received packets
++ .  IM_RX_OVRN_INT, because I have to kick the receiver
++ .  IM_MDINT, for PHY Register 18 Status Changes
++ --------------------------------------------------------------------------*/
++#define SMC_INTERRUPT_MASK   (IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | \
++      IM_MDINT)
++
++
++#ifdef CONFIG_SYSCTL
++/*
++ * Declarations for the sysctl interface, which allows users the ability to
++ * control the finer aspects of the LAN91C111 chip.  Since the smc
++ * module currently registers its sysctl table dynamically, the sysctl path
++ * for module FOO is /proc/sys/dev/ethX/FOO
++ */
++#define CTL_SMC         (CTL_BUS+1389)      // arbitrary and hopefully unused
++
++enum {
++      CTL_SMC_INFO = 1,       // Sysctl files information
++      CTL_SMC_SWVER,          // Driver Software Version Info
++      CTL_SMC_SWFDUP,         // Switched Full Duplex Mode
++      CTL_SMC_EPHLOOP,        // EPH Block Internal Loopback
++      CTL_SMC_MIIOP,          // MII Operation
++      CTL_SMC_AUTONEG,        // Auto-negotiate Mode
++      CTL_SMC_RFDUPLX,        // Request Full Duplex Mode
++      CTL_SMC_RSPEED,         // Request Speed Selection
++      CTL_SMC_AFDUPLX,        // Actual Full Duplex Mode
++      CTL_SMC_ASPEED,         // Actual Speed Selection
++      CTL_SMC_LNKFAIL,        // Link Failed
++      CTL_SMC_FORCOL,         // Force a Collision
++      CTL_SMC_FILTCAR,        // Filter Carrier
++      CTL_SMC_FREEMEM,        // Free Buffer Memory
++      CTL_SMC_TOTMEM,         // Total Buffer Memory
++      CTL_SMC_LEDA,           // Output of LED-A
++      CTL_SMC_LEDB,           // Output of LED-B
++      CTL_SMC_CHIPREV,        // LAN91C111 Chip Revision ID
++#if SMC_DEBUG > 1
++      // Register access for debugging
++      CTL_SMC_REG_BSR,        // Bank Select
++      CTL_SMC_REG_TCR,        // Transmit Control
++      CTL_SMC_REG_ESR,        // EPH Status
++      CTL_SMC_REG_RCR,        // Receive Control
++      CTL_SMC_REG_CTRR,       // Counter
++      CTL_SMC_REG_MIR,        // Memory Information
++      CTL_SMC_REG_RPCR,       // Receive/Phy Control
++      CTL_SMC_REG_CFGR,       // Configuration
++      CTL_SMC_REG_BAR,        // Base Address
++      CTL_SMC_REG_IAR0,       // Individual Address 0
++      CTL_SMC_REG_IAR1,       // Individual Address 1
++      CTL_SMC_REG_IAR2,       // Individual Address 2
++      CTL_SMC_REG_GPR,        // General Purpose
++      CTL_SMC_REG_CTLR,       // Control
++      CTL_SMC_REG_MCR,        // MMU Command
++      CTL_SMC_REG_PNR,        // Packet Number
++      CTL_SMC_REG_FPR,        // FIFO Ports
++      CTL_SMC_REG_PTR,        // Pointer
++      CTL_SMC_REG_DR,         // Data
++      CTL_SMC_REG_ISR,        // Interrupt Status
++      CTL_SMC_REG_MTR1,       // Multicast Table Entry 1
++      CTL_SMC_REG_MTR2,       // Multicast Table Entry 2
++      CTL_SMC_REG_MTR3,       // Multicast Table Entry 3
++      CTL_SMC_REG_MTR4,       // Multicast Table Entry 4
++      CTL_SMC_REG_MIIR,       // Management Interface
++      CTL_SMC_REG_REVR,       // Revision
++      CTL_SMC_REG_ERCVR,      // Early RCV
++      CTL_SMC_REG_EXTR,       // External
++      CTL_SMC_PHY_CTRL,       // PHY Control
++      CTL_SMC_PHY_STAT,       // PHY Status
++      CTL_SMC_PHY_ID1,        // PHY ID1
++      CTL_SMC_PHY_ID2,        // PHY ID2
++      CTL_SMC_PHY_ADC,        // PHY Advertise Capability
++      CTL_SMC_PHY_REMC,       // PHY Advertise Capability
++      CTL_SMC_PHY_CFG1,       // PHY Configuration 1
++      CTL_SMC_PHY_CFG2,       // PHY Configuration 2
++      CTL_SMC_PHY_INT,        // PHY Interrupt/Status Output
++      CTL_SMC_PHY_MASK,       // PHY Interrupt/Status Mask
++#endif
++      // ---------------------------------------------------
++      CTL_SMC_LAST_ENTRY      // Add new entries above the line
++};
++#endif // CONFIG_SYSCTL
++#endif  /* _SMC_91111_H_ */
diff --git a/kernel/prepare b/kernel/prepare
new file mode 100755 (executable)
index 0000000..78df2f6
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+mkdir $1
+
+(cd $1 ; tar -jxvf ../../packages/linux-2.4.31.tar.bz2)
+
+./patch $1
diff --git a/lbox_border/README b/lbox_border/README
new file mode 100644 (file)
index 0000000..8d8c5e7
--- /dev/null
@@ -0,0 +1,3 @@
+autobuild - does clean, build
+build     - creates the module
+clean     - removes the module
diff --git a/lbox_border/autobuild b/lbox_border/autobuild
new file mode 100755 (executable)
index 0000000..20a6f3f
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+./clean
+./build
diff --git a/lbox_border/build b/lbox_border/build
new file mode 100755 (executable)
index 0000000..cde7c12
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+LKERN=../kernel/dev/linux-2.4.31/include
+
+. ../crosstool/cross-var
+${CROSS}gcc -I${LKERN} -DLINUX -DMODULE -D__KERNEL__ -Wa,-m405 -c lbox_border.c
+
diff --git a/lbox_border/clean b/lbox_border/clean
new file mode 100755 (executable)
index 0000000..96402bc
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+rm -f lbox_border.o
diff --git a/lbox_border/lbox_border.c b/lbox_border/lbox_border.c
new file mode 100644 (file)
index 0000000..d128c48
--- /dev/null
@@ -0,0 +1,55 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Calderbank");
+
+static ssize_t do_write(struct file  *file,
+                        const char   *buf,
+                        size_t       length,
+                        loff_t       *offset)
+{
+  int i;
+  char c;
+  int border = -1;
+
+  for (i=0; i<3 && i<length; i++)
+  {
+    get_user(c, buf+i);
+    if (c < '0' || c > '9') break;
+    if (i == 0) border = 0; else border *= 10;
+    border += c - '0';
+  }
+
+  if (border != -1) asm volatile("mtdcr 0x17b,%0" : : "r" (border));
+  return length;
+}
+
+static struct file_operations f_ops =
+{
+  owner:   THIS_MODULE,
+  write:   do_write
+};
+
+int init_module(void)
+{
+  struct proc_dir_entry *entry;
+  entry = create_proc_entry("lbox_border", S_IWUSR, NULL);
+  if (!entry) return -EIO;
+  entry->proc_fops = &f_ops;
+  MOD_INC_USE_COUNT; /* Just prevent removal - simple */
+  return 0;
+}
+
+void cleanup_module(void)
+{
+  remove_proc_entry("lbox_border", NULL);
+}
+
+long __get_user_bad(void)
+{
+  return 0;
+}
diff --git a/makedevenv b/makedevenv
new file mode 100755 (executable)
index 0000000..d6aec1b
--- /dev/null
@@ -0,0 +1,144 @@
+#!/bin/bash
+
+WGET=wget
+TAR=tar
+GZIP=gzip
+BZIP2=bzip2
+PATCH=patch
+AUTOCONF=autoconf
+MAKE=make
+GIT=git
+# The following are required by crosstool
+BISON=bison
+FLEX=flex
+
+PACKAGES_DIR=packages
+DOWNLOAD_PREFIX=http://www.loggytronic.com/dl/
+
+FILE_MVPDEVFS=mvpdevfs-4.tar.gz
+
+# Files used by the script packages
+SOURCEFILES="crosstool-0.43.tar.gz linux-2.4.31.tar.bz2 busybox-1.00.tar.bz2 jpegsrc.v6b.tar.gz genext2fs-1.4.tar.gz"
+# And files downloaded by crosstool:
+SOURCEFILES+=" binutils-2.15.tar.bz2 glibc-2.2.5.tar.gz linux-2.6.8.tar.bz2 gcc-3.4.5.tar.bz2 glibc-linuxthreads-2.2.5.tar.gz"
+
+set -e
+
+# ----------------------------------------------
+
+makeDir()
+{
+  if ! mkdir -p $1
+  then
+    echo "Error: could not create directory: $1"
+    exit
+  fi
+}
+
+downloadFile()
+{
+  if [ ! -r ${PACKAGES_DIR}/$1 -o ! -s ${PACKAGES_DIR}/$1 ]
+  then
+    if ! $WGET -O ${PACKAGES_DIR}/$1 ${DOWNLOAD_PREFIX}$1
+    then
+      echo "Error: could not download $1"
+      exit
+    fi
+  fi
+}
+
+checkProg()
+{
+  if [ -x /bin/$1 ] || [ -x /usr/bin/$1 ]
+  then
+    return 0
+  else
+    echo "$1 not found in /bin or /usr/bin."
+    exit 1
+  fi
+}
+
+# The Start
+
+echo
+echo "VOMP Development Environment Setup Script (git version)"
+echo
+
+TOP=`pwd`
+
+# Test for prerequisites
+
+if [ -L /bin/sh ] && [ $(readlink /bin/sh) = dash ]
+then
+  echo "Your /bin/sh symlink links to dash which causes the crosstool build to fail."
+  echo "Please point /bin/sh to another shell (bash works)."
+  exit 1
+fi
+
+checkProg $WGET
+checkProg $TAR
+checkProg $GZIP
+checkProg $BZIP2
+checkProg $PATCH
+checkProg $AUTOCONF
+checkProg $MAKE
+checkProg $GIT
+checkProg $BISON
+checkProg $FLEX
+
+# Make directories
+
+makeDir $PACKAGES_DIR
+
+# Download files
+
+downloadFile $FILE_MVPDEVFS
+
+for i in $SOURCEFILES ; do
+  downloadFile $i
+done
+
+# Build cross compiler
+
+cd ${TOP}/crosstool
+./autobuild
+
+# Build kernels
+
+cd ${TOP}/kernel
+./autobuild
+
+# Build busybox
+
+cd ${TOP}/busybox
+./autobuild
+
+# Build JPEG
+
+cd ${TOP}/jpeg
+./autobuild
+
+# Build kernel module
+
+cd ${TOP}/lbox_border
+./autobuild
+
+# Get client and build for dongle
+
+cd $TOP
+$GIT clone http://git.vomp.tv/vompclient.git client
+cd client
+$MAKE release
+
+# Build a dongle
+
+cd ${TOP}/dongle
+./autobuild
+
+# Done
+
+echo
+echo "Done. A dongle should have been created as dongle/vomp-dongle"
+echo "Optionally you can set-up an NFS root development environment by following the"
+echo "MVP-Filesystem->DHCP->TFTP->NFS guide."
+echo