From: Chris Tallon Date: Sat, 23 Jun 2012 15:04:02 +0000 (+0100) Subject: Initial import X-Git-Url: https://git.vomp.tv/gitweb/?a=commitdiff_plain;h=ab9968a9e41f2629ed4a16bccf0471d5d6213689;p=makedevenv.git Initial import --- ab9968a9e41f2629ed4a16bccf0471d5d6213689 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a868cc5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +client +packages diff --git a/busybox/README b/busybox/README new file mode 100644 index 0000000..923dd42 --- /dev/null +++ b/busybox/README @@ -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 index 0000000..7b708f2 --- /dev/null +++ b/busybox/autobuild @@ -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 index 0000000..4f81d59 --- /dev/null +++ b/busybox/build @@ -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 index 0000000..4c42a1c --- /dev/null +++ b/busybox/clean @@ -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 index 0000000..9badda3 --- /dev/null +++ b/busybox/config-dev-3 @@ -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 index 0000000..e1f26b3 --- /dev/null +++ b/busybox/config-dongle-2 @@ -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 index 0000000..52109d7 --- /dev/null +++ b/busybox/fullclean @@ -0,0 +1,3 @@ +#!/bin/bash + +rm -rf dev dongle diff --git a/busybox/prepare b/busybox/prepare new file mode 100755 index 0000000..91b7f33 --- /dev/null +++ b/busybox/prepare @@ -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 index 0000000..b96c06f --- /dev/null +++ b/crosstool/README @@ -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 index 0000000..0661f16 --- /dev/null +++ b/crosstool/autobuild @@ -0,0 +1,5 @@ +#!/bin/bash + +./fullclean +./prepare +./build diff --git a/crosstool/build b/crosstool/build new file mode 100755 index 0000000..b3a51d1 --- /dev/null +++ b/crosstool/build @@ -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 index 0000000..aac4ae2 --- /dev/null +++ b/crosstool/clean @@ -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 index 0000000..038828c --- /dev/null +++ b/crosstool/fullclean @@ -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 index 0000000..6549cd1 --- /dev/null +++ b/crosstool/glibc-2.2.5-allow-gcc-4.0-configure.patch @@ -0,0 +1,22 @@ +Fixes +checking version of powerpc-405-linux-gnu-gcc ... 4.0.0, bad +checking for gnumake... no +checking for gmake... no +checking for make... make +checking version of make... 3.80, ok +configure: error: +*** These critical programs are missing or too old:gcc + + +--- glibc-2.2.5/configure.old 2005-03-10 00:23:46.374213600 -0800 ++++ glibc-2.2.5/configure 2005-03-10 00:25:13.313996744 -0800 +@@ -1476,7 +1476,7 @@ + ac_prog_version=`$CC -v 2>&1 | sed -n 's/^.*version \([egcygnustpi-]*[0-9.]*\).*$/\1/p'` + case $ac_prog_version in + '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;; +- *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-*) ++ *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-*) + ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;; + *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;; + + diff --git a/crosstool/prepare b/crosstool/prepare new file mode 100755 index 0000000..f7d81d6 --- /dev/null +++ b/crosstool/prepare @@ -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 index 0000000..0ceaa25 --- /dev/null +++ b/dongle/README @@ -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 index 0000000..a716723 --- /dev/null +++ b/dongle/autobuild @@ -0,0 +1,4 @@ +#!/bin/bash +./fullclean +./prepare +./build diff --git a/dongle/build b/dongle/build new file mode 100755 index 0000000..8daa9c0 --- /dev/null +++ b/dongle/build @@ -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 index 0000000..e95f950 --- /dev/null +++ b/dongle/devtable @@ -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 index 0000000..0ff07bb --- /dev/null +++ b/dongle/fullclean @@ -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 index 0000000..5a7e056 --- /dev/null +++ b/dongle/prepare @@ -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 index 0000000..2d66930 --- /dev/null +++ b/dongle/tofs/dev/fb @@ -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 index 0000000..d920e94 --- /dev/null +++ b/dongle/tofs/dev/kcore @@ -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 index 0000000..3d81984 --- /dev/null +++ b/dongle/tofs/dev/mouse @@ -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 index 0000000..5f76aa2 --- /dev/null +++ b/dongle/tofs/dev/ram @@ -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 index 0000000..b5b544a --- /dev/null +++ b/dongle/tofs/dev/ramdisk @@ -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 index 0000000..c67586e --- /dev/null +++ b/dongle/tofs/dev/stderr @@ -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 index 0000000..2825dc0 --- /dev/null +++ b/dongle/tofs/dev/stdin @@ -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 index 0000000..35e0f62 --- /dev/null +++ b/dongle/tofs/dev/stdout @@ -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 index 0000000..e87aabc --- /dev/null +++ b/dongle/tofs/etc/fstab @@ -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 index 0000000..39dbbc7 --- /dev/null +++ b/dongle/tofs/etc/group @@ -0,0 +1 @@ +root::0: diff --git a/dongle/tofs/etc/hosts b/dongle/tofs/etc/hosts new file mode 100644 index 0000000..d0bdd91 --- /dev/null +++ b/dongle/tofs/etc/hosts @@ -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 index 0000000..cad6a5b --- /dev/null +++ b/dongle/tofs/etc/inittab @@ -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 index 0000000..1418336 --- /dev/null +++ b/dongle/tofs/etc/issue.net @@ -0,0 +1,3 @@ +VOMP Client + + diff --git a/dongle/tofs/etc/passwd b/dongle/tofs/etc/passwd new file mode 100644 index 0000000..233d68f --- /dev/null +++ b/dongle/tofs/etc/passwd @@ -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 index 0000000..9a39bd1 --- /dev/null +++ b/dongle/tofs/etc/profile @@ -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 index 0000000..e419989 --- /dev/null +++ b/dongle/tofs/etc/rcS @@ -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 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 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 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 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 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 index 0000000..452a106 --- /dev/null +++ b/jpeg/README @@ -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 index 0000000..a716723 --- /dev/null +++ b/jpeg/autobuild @@ -0,0 +1,4 @@ +#!/bin/bash +./fullclean +./prepare +./build diff --git a/jpeg/build b/jpeg/build new file mode 100755 index 0000000..c8dec8e --- /dev/null +++ b/jpeg/build @@ -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 index 0000000..8a1e717 --- /dev/null +++ b/jpeg/clean @@ -0,0 +1,4 @@ +#!/bin/bash + +cd jpeg-6b +make distclean diff --git a/jpeg/fullclean b/jpeg/fullclean new file mode 100755 index 0000000..59725dd --- /dev/null +++ b/jpeg/fullclean @@ -0,0 +1,3 @@ +#!/bin/bash + +rm -rf jpeg-6b diff --git a/jpeg/prepare b/jpeg/prepare new file mode 100755 index 0000000..07e4d1e --- /dev/null +++ b/jpeg/prepare @@ -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 index 0000000..299ad9d --- /dev/null +++ b/kernel/README @@ -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 index 0000000..60ec99f --- /dev/null +++ b/kernel/autobuild @@ -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 index 0000000..b450f2a --- /dev/null +++ b/kernel/build @@ -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 index 0000000..1b78e73 --- /dev/null +++ b/kernel/clean @@ -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 index 0000000..a7bc12f --- /dev/null +++ b/kernel/config-dev-5 @@ -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 index 0000000..dee2c02 --- /dev/null +++ b/kernel/config-dongle-2 @@ -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 index 0000000..52109d7 --- /dev/null +++ b/kernel/fullclean @@ -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 index 0000000..548f419 --- /dev/null +++ b/kernel/otherpatches/Makefile.patch @@ -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 index 0000000..31ad563 --- /dev/null +++ b/kernel/otherpatches/bash4_correction.patch @@ -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 index 0000000..8750698 --- /dev/null +++ b/kernel/otherpatches/dongle_version.h @@ -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 index 0000000..b4594f6 --- /dev/null +++ b/kernel/otherpatches/fullduplex.patch @@ -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 index 0000000..c75bc30 --- /dev/null +++ b/kernel/otherpatches/ppcfix.patch @@ -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 + #include + #include ++#include + + /* 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 index 0000000..c9e9719 --- /dev/null +++ b/kernel/patch @@ -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 index 0000000..020f959 --- /dev/null +++ b/kernel/patches-2.4.31/architecture.patch @@ -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 index 0000000..ae063ca --- /dev/null +++ b/kernel/patches-2.4.31/clockfix.patch @@ -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 index 0000000..b4f5ca2 --- /dev/null +++ b/kernel/patches-2.4.31/kexec-ppc-2.4.patch @@ -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 ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++//#include ++#include ++ ++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 ++ * ++ * 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 ++#include ++ ++#include ++ ++#define PAGE_SIZE 4096 /* must be same value as in */ ++ ++ /* ++ * 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 ++#include + + #ifdef CONFIG_APUS + #include +@@ -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 ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 , 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 ++ * ++ * This source code is licensed under the GNU General Public License, ++ * Version 2. See the file COPYING for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++//#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* 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 . ++ * ++ * 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 + #include + #include ++#include + + 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 + #include + ++#include ++#include ++ + #include + #include + +@@ -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 index 0000000..3ba171e --- /dev/null +++ b/kernel/patches-2.4.31/memsize.patch @@ -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 index 0000000..181fede --- /dev/null +++ b/kernel/patches-2.4.31/mvp-version.patch @@ -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 ++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 index 0000000..ac1e23a --- /dev/null +++ b/kernel/patches-2.4.31/ppc405-wdt.patch @@ -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. ++ * Debbie Chu ++ * Frank Rowand ++ * ++ * 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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=" 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 index 0000000..7619e85 --- /dev/null +++ b/kernel/patches-2.4.31/redwood.c @@ -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 +#include +#include +#include + +#include +#include +#include + +#include +#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 "); +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 index 0000000..203022c --- /dev/null +++ b/kernel/patches-2.4.31/sdram-bank1.patch @@ -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 ++#include ++ ++#include ++#include ++ ++#if CONFIG_MODVERSIONS == 1 ++#define MODVERSIONS ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#define KDBG(fmt, args...) if(1) printk(": " 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 index 0000000..27b520e --- /dev/null +++ b/kernel/patches-2.4.31/smc91111.patch @@ -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 ++ . ++ . 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#ifdef CONFIG_SYSCTL ++#include ++#include ++#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<>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 == , 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_cur_mode |= (word)(val<rpc_cur_mode); ++ break; ++ ++ case CTL_SMC_LEDB: ++ val &= 0x07; // Restrict to 3 ls bits ++ lp->rpc_cur_mode &= ~(word)(0x07<rpc_cur_mode |= (word)(val<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 index 0000000..78df2f6 --- /dev/null +++ b/kernel/prepare @@ -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 index 0000000..8d8c5e7 --- /dev/null +++ b/lbox_border/README @@ -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 index 0000000..20a6f3f --- /dev/null +++ b/lbox_border/autobuild @@ -0,0 +1,4 @@ +#!/bin/bash + +./clean +./build diff --git a/lbox_border/build b/lbox_border/build new file mode 100755 index 0000000..cde7c12 --- /dev/null +++ b/lbox_border/build @@ -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 index 0000000..96402bc --- /dev/null +++ b/lbox_border/clean @@ -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 index 0000000..d128c48 --- /dev/null +++ b/lbox_border/lbox_border.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +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 '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 index 0000000..d6aec1b --- /dev/null +++ b/makedevenv @@ -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