add netboot support.

This commit is contained in:
okuji 1999-09-14 06:55:57 +00:00
parent 694616c180
commit be514997d2
51 changed files with 9152 additions and 92 deletions

106
ChangeLog
View file

@ -1,3 +1,109 @@
1999-09-14 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* configure.in (--enable-ne): Made the description more clear.
(--enable-nepci): Likewise.
(--enable-wd): Likewise.
(--enable-t503): Likewise.
(--enable-t509): Likewise.
(--enable-3c59x): Likewise.
(--enable-lance): Likewise.
(--enable-cs): Likewise.
(--enable-eepro100): Likewise.
(--enable-wd-default_mem): Renamed to ...
(--enable-wd-default-mem): ... this.
(--enable-cs-scan): Corrected the description.
(NETBOOT_SUPPORT): Defined if NET_CFLAGS is not empty.
* stage2/Makefile.am (stage2_exec_LDADD): Defined only if
NETBOOT_SUPPORT is true.
* netboot/Makefile.am (LIBDRIVERS): New variable. If
NETBOOT_SUPPORT is true, set to libdriver.a, otherwise set to an
empty string.
(noinst_LIBRARIES): Set to LIBDRIVERS.
(DRIVERS): Added 3c509.h, cs89x0.h and ns8390.h.
(libdrivers_a_SOURCES): Added byteorder.h, config.h, if.h, io.h,
ip.h, netboot.h, netdevice.h, nic.h and pic.h.
(libdrivers_a_CFLAGS): Added -fno-builtin and -nostdinc and
removed -O2.
* stage2/char_io.c (grub_sprintf): Added parenthesises to avoid
gcc warnings.
* stage2/gunzip.c (gunzip_test_header): Check if FSYS_TYPE is
TFTP. If so, set IS_TFTP to non-zero, otherwise to zero. And,
use IS_TFTP to check if we have GZIP_CRC instead of the equation
"FILEMAX == 16 * 1024 * 1024".
1999-09-13 Edmund GRIMLEY EVANS <edmundo@rano.demon.co.uk>
The netboot support in the Dresden version of GRUB is integrated.
* Makefile.am (SUBDIRS): Added netboot.
* configure.in (--enable-tftp): New option.
(--enable-ne): Likewise.
(--enable-nepci): Likewise.
(--enable-wd): Likewise.
(--enable-t503): Likewise.
(--enable-t509): Likewise.
(--enable-3c59x): Likewise.
(--enable-lance): Likewise.
(--enable-cs): Likewise.
(--enable-eepro100): Likewise.
(--enable-ne-scan): Likewise.
(--enable-wd-default_mem): Likewise.
(--enable-cs-scan): Likewise.
(NET_CFLAGS): New variable.
(NET_EXTRAFLAGS): Likewise.
Do AC_OUTPUT for netboot/Makefile as well.
* stage1/stage1.S: Set the number of sectors for Stage 2 to 130.
* stage1/stage1_lba.S: Likewise.
* stage2/Makefile.am (stage2_exec_LDADD): Added
../netboot/libdrivers.a.
* stage2/asm.S [!STAGE1_5] (currticks): New function.
* stage2/char_io.c [!STAGE1_5] (grub_sprintf): Likewise.
[!STAGE1_5] (grub_memcmp): Likewise.
* stage2/disk_io.c (fsys_table) [FSYS_TFTP]: Added an entry for
tftp.
(sane_partition) [!STAGE1_5]: If CURRENT_DRIVE is a network
drive, return 1.
(real_open_partition) [!STAGE1_5]: Likewise.
(set_device): If DEVICE contains a network drive, set
CURRENT_DRIVE to 0x20.
* stage2/filesys.h [FSYS_TFTP] (FSYS_TFTP_NUM): Defined as 1.
[!FSYS_TFTP] (FSYS_TFTP_NUM): Defined as 0.
(NUM_FSYS): Added FSYS_TFTP_NUM.
* stage2/gunzip.c (gunzip_test_header): If FILEMAX >= 16MB, do
not try to examine the last 8 bytes of the file. This is
required for compressed files by TFTP.
* stage2/shared.h (sprintf): New macro.
(memcmp): Likewise.
(currticks): Declared.
(grub_sprintf): Likewise.
(grub_memcmp): Likewise.
* stage2/size_test: Set the maximum size of Stage 2 to 66560.
* netboot/3c509.c: New file.
* netboot/3c509.h: Likewise.
* netboot/3c59x.c: Likewise.
* netboot/Makefile.am: Likewise.
* netboot/Makefile.in: Likewise.
* netboot/byteorder.h: Likewise.
* netboot/compile: Likewise.
* netboot/config.c: Likewise.
* netboot/config.h: Likewise.
* netboot/cs89x0.c: Likewise.
* netboot/cs89x0.h: Likewise.
* netboot/eepro100.c: Likewise.
* netboot/fsys_tftp.c: Likewise.
* netboot/if.h: Likewise.
* netboot/io.h: Likewise.
* netboot/ip.c: Likewise.
* netboot/ip.h: Likewise.
* netboot/lance.c: Likewise.
* netboot/netboot.h: Likewise.
* netboot/netdevice.h: Likewise.
* netboot/nic.h: Likewise.
* netboot/ns8390.c: Likewise.
* netboot/ns8390.h: Likewise.
* netboot/pci.c: Likewise.
* netboot/pci.h: Likewise.
1999-09-13 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp> 1999-09-13 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* configure.in (--enable-maintainer-mode): Do not use our own * configure.in (--enable-maintainer-mode): Do not use our own

View file

@ -1,4 +1,4 @@
SUBDIRS = stage1 stage2 grub docs debian SUBDIRS = stage1 netboot stage2 grub docs debian
EXTRA_DIST = BUGS EXTRA_DIST = BUGS
# We get $(PACKAGE) and $(VERSION) from debian/changelog. # We get $(PACKAGE) and $(VERSION) from debian/changelog.

View file

@ -69,6 +69,8 @@ GRUB_LIBS = @GRUB_LIBS@
LD = @LD@ LD = @LD@
MAINT = @MAINT@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
NET_CFLAGS = @NET_CFLAGS@
NET_EXTRAFLAGS = @NET_EXTRAFLAGS@
OBJCOPY = @OBJCOPY@ OBJCOPY = @OBJCOPY@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
PERL = @PERL@ PERL = @PERL@
@ -81,7 +83,7 @@ host_vendor = @host_vendor@
install_sh = @install_sh@ install_sh = @install_sh@
SUBDIRS = stage1 stage2 grub docs debian SUBDIRS = stage1 netboot stage2 grub docs debian
EXTRA_DIST = BUGS EXTRA_DIST = BUGS
subdir = . subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4

1
NEWS
View file

@ -22,6 +22,7 @@ New in 0.5.93:
* The option `--no-floppy' force the grub shell to assume that there is * The option `--no-floppy' force the grub shell to assume that there is
no floppy, and the option `--probe-second-floppy' enables the probe of no floppy, and the option `--probe-second-floppy' enables the probe of
the second floppy drive. the second floppy drive.
* Integrated the netboot support in the Dresden version of GRUB.
New in 0.5.92 - 1999-07-26: New in 0.5.92 - 1999-07-26:
* Bug fixes (i.e. Stage 1.5 can work fine again). * Bug fixes (i.e. Stage 1.5 can work fine again).

1
THANKS
View file

@ -11,6 +11,7 @@ Bradford Hovinen <hovinen@redrose.net>
Brian Brunswick <brian@skarpsey.demon.co.uk> Brian Brunswick <brian@skarpsey.demon.co.uk>
Bryan Ford <baford@cs.utah.edu> Bryan Ford <baford@cs.utah.edu>
Dan J. Walters <djw@cs.utexas.edu> Dan J. Walters <djw@cs.utexas.edu>
Edmund GRIMLEY EVANS <edmundo@rano.demon.co.uk>
Edward Killips <ekillips@triton.net> Edward Killips <ekillips@triton.net>
Eric Hanchrow <erich@microsoft.com> Eric Hanchrow <erich@microsoft.com>
Heiko Schroeder <heiko@pool.informatik.rwth-aachen.de> Heiko Schroeder <heiko@pool.informatik.rwth-aachen.de>

7
TODO
View file

@ -7,8 +7,6 @@ type''. We need this for clean Hurd install floppies.
Add a real scripting language, possibly retaining backward Add a real scripting language, possibly retaining backward
compatibility so that old config files can be used. compatibility so that old config files can be used.
Look at the network booting patches from L4.
Add internationalization support, emulating gettext as much as is Add internationalization support, emulating gettext as much as is
feasible. feasible.
@ -25,8 +23,13 @@ larger than 16MB can be read.
??? Add command for modifying partition types. ??? Add command for modifying partition types.
Add OpenBSD support. The recent versions cannot be loaded.
Fix-up FreeBSD, NetBSD (and OpenBSD ?) command-line boot parameters Fix-up FreeBSD, NetBSD (and OpenBSD ?) command-line boot parameters
Add a new installation command, such as `setup', which should be easier
to use and more automatic than the command `install'.
Add keyboard layout configuration support. Add keyboard layout configuration support.
Clean up and enhance the manuals, especially concept indexes. Clean up and enhance the manuals, especially concept indexes.

299
configure vendored
View file

@ -22,8 +22,34 @@ ac_help="$ac_help
--disable-ffs disable FFS support in Stage 2" --disable-ffs disable FFS support in Stage 2"
ac_help="$ac_help ac_help="$ac_help
--disable-minix disable Minix fs support in Stage 2" --disable-minix disable Minix fs support in Stage 2"
ac_help="$ac_help
--enable-tftp enable TFTP support in Stage 2"
ac_help="$ac_help ac_help="$ac_help
--disable-gunzip disable decompression in Stage 2" --disable-gunzip disable decompression in Stage 2"
ac_help="$ac_help
--enable-ne enable NE1000/2000 network driver in Stage 2"
ac_help="$ac_help
--enable-nepci enable PCI NE2000 network driver in Stage 2"
ac_help="$ac_help
--enable-wd enable WD/SMC network driver in Stage 2"
ac_help="$ac_help
--enable-t503 enable 3C503 network driver in Stage 2"
ac_help="$ac_help
--enable-t509 enable 3C509 network driver in Stage 2"
ac_help="$ac_help
--enable-3c59x enable 3C59x network driver in Stage 2"
ac_help="$ac_help
--enable-lance enable LANCE network driver in Stage 2"
ac_help="$ac_help
--enable-cs enable CS89*0 network driver in Stage 2"
ac_help="$ac_help
--enable-eepro100 enable EtherExpress100 network driver in Stage 2"
ac_help="$ac_help
--enable-ne-scan set the parameter for NE network driver"
ac_help="$ac_help
--enable-wd-default-mem set the parameter for WD network driver"
ac_help="$ac_help
--enable-cs-scan set the parameter for CS network driver"
# Initialize some variables set by options. # Initialize some variables set by options.
# The variables have the same names as the options, with # The variables have the same names as the options, with
@ -569,7 +595,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh. # ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:573: checking for a BSD compatible install" >&5 echo "configure:599: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then if test -z "$INSTALL"; then
if eval "test \"\${ac_cv_path_install+set}\" = set"; then if eval "test \"\${ac_cv_path_install+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
@ -626,7 +652,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6 echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
echo "configure:630: checking whether build environment is sane" >&5 echo "configure:656: checking whether build environment is sane" >&5
# Just in case # Just in case
sleep 1 sleep 1
echo timestamp > conftestfile echo timestamp > conftestfile
@ -687,7 +713,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args. # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2 set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:691: checking for $ac_word" >&5 echo "configure:717: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_AWK+set}\" = set"; then if eval "test \"\${ac_cv_prog_AWK+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -717,7 +743,7 @@ test -n "$AWK" && break
done done
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
echo "configure:721: checking whether ${MAKE-make} sets \${MAKE}" >&5 echo "configure:747: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
@ -766,7 +792,7 @@ EOF
missing_dir=`cd $ac_aux_dir && pwd` missing_dir=`cd $ac_aux_dir && pwd`
echo $ac_n "checking for working aclocal""... $ac_c" 1>&6 echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
echo "configure:770: checking for working aclocal" >&5 echo "configure:796: checking for working aclocal" >&5
# Run test in a subshell; some versions of sh will print an error if # Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected. # an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh. # Redirect stdin to placate older versions of autoconf. Sigh.
@ -779,7 +805,7 @@ else
fi fi
echo $ac_n "checking for working autoconf""... $ac_c" 1>&6 echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
echo "configure:783: checking for working autoconf" >&5 echo "configure:809: checking for working autoconf" >&5
# Run test in a subshell; some versions of sh will print an error if # Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected. # an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh. # Redirect stdin to placate older versions of autoconf. Sigh.
@ -792,7 +818,7 @@ else
fi fi
echo $ac_n "checking for working automake""... $ac_c" 1>&6 echo $ac_n "checking for working automake""... $ac_c" 1>&6
echo "configure:796: checking for working automake" >&5 echo "configure:822: checking for working automake" >&5
# Run test in a subshell; some versions of sh will print an error if # Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected. # an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh. # Redirect stdin to placate older versions of autoconf. Sigh.
@ -805,7 +831,7 @@ else
fi fi
echo $ac_n "checking for working autoheader""... $ac_c" 1>&6 echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
echo "configure:809: checking for working autoheader" >&5 echo "configure:835: checking for working autoheader" >&5
# Run test in a subshell; some versions of sh will print an error if # Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected. # an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh. # Redirect stdin to placate older versions of autoconf. Sigh.
@ -818,7 +844,7 @@ else
fi fi
echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6 echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
echo "configure:822: checking for working makeinfo" >&5 echo "configure:848: checking for working makeinfo" >&5
# Run test in a subshell; some versions of sh will print an error if # Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected. # an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh. # Redirect stdin to placate older versions of autoconf. Sigh.
@ -838,7 +864,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args. # Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2 set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:842: checking for $ac_word" >&5 echo "configure:868: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_AMTAR+set}\" = set"; then if eval "test \"\${ac_cv_prog_AMTAR+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -882,7 +908,7 @@ fi
echo $ac_n "checking host system type""... $ac_c" 1>&6 echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:886: checking host system type" >&5 echo "configure:912: checking host system type" >&5
if test "x$ac_cv_host" = "x" || (test "x$host" != "xNONE" && test "x$host" != "x$ac_cv_host_alias"); then if test "x$ac_cv_host" = "x" || (test "x$host" != "xNONE" && test "x$host" != "x$ac_cv_host_alias"); then
# Make sure we can run config.sub. # Make sure we can run config.sub.
@ -935,7 +961,7 @@ esac
# #
echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
echo "configure:939: checking whether to enable maintainer-specific portions of Makefiles" >&5 echo "configure:965: checking whether to enable maintainer-specific portions of Makefiles" >&5
# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
if test "${enable_maintainer_mode+set}" = set; then if test "${enable_maintainer_mode+set}" = set; then
enableval="$enable_maintainer_mode" enableval="$enable_maintainer_mode"
@ -961,7 +987,7 @@ if test "x$enable_maintainer_mode" = xyes; then
# Extract the first word of "perl", so it can be a program name with args. # Extract the first word of "perl", so it can be a program name with args.
set dummy perl; ac_word=$2 set dummy perl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:965: checking for $ac_word" >&5 echo "configure:991: checking for $ac_word" >&5
if eval "test \"\${ac_cv_path_PERL+set}\" = set"; then if eval "test \"\${ac_cv_path_PERL+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1009,7 +1035,7 @@ fi
echo $ac_n "checking build system type""... $ac_c" 1>&6 echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:1013: checking build system type" >&5 echo "configure:1039: checking build system type" >&5
if test "x$ac_cv_build" = "x" || (test "x$build" != "xNONE" && test "x$build" != "x$ac_cv_build_alias"); then if test "x$ac_cv_build" = "x" || (test "x$build" != "xNONE" && test "x$build" != "x$ac_cv_build_alias"); then
# Make sure we can run config.sub. # Make sure we can run config.sub.
@ -1056,7 +1082,7 @@ fi
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2 set dummy ${ac_tool_prefix}gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1060: checking for $ac_word" >&5 echo "configure:1086: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1088,7 +1114,7 @@ fi
# Extract the first word of "gcc", so it can be a program name with args. # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2 set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1092: checking for $ac_word" >&5 echo "configure:1118: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1118,7 +1144,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args. # Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2 set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1122: checking for $ac_word" >&5 echo "configure:1148: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1169,7 +1195,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args. # Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2 set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1173: checking for $ac_word" >&5 echo "configure:1199: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then if eval "test \"\${ac_cv_prog_CC+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1201,7 +1227,7 @@ fi
fi fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:1205: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works" >&5 echo "configure:1231: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) works" >&5
ac_ext=c ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@ -1212,12 +1238,12 @@ cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext << EOF cat > conftest.$ac_ext << EOF
#line 1216 "configure" #line 1242 "configure"
#include "confdefs.h" #include "confdefs.h"
main(){return(0);} main(){return(0);}
EOF EOF
if { (eval echo configure:1221: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then if { (eval echo configure:1247: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler. # If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then if (./conftest; exit) 2>/dev/null; then
@ -1243,12 +1269,12 @@ if test $ac_cv_prog_cc_works = no; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:1247: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "configure:1273: checking whether the C compiler ($CC $CFLAGS $CPPFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:1252: checking whether we are using GNU C" >&5 echo "configure:1278: checking whether we are using GNU C" >&5
if eval "test \"\${ac_cv_prog_gcc+set}\" = set"; then if eval "test \"\${ac_cv_prog_gcc+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1257,7 +1283,7 @@ else
yes; yes;
#endif #endif
EOF EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1261: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1287: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes ac_cv_prog_gcc=yes
else else
ac_cv_prog_gcc=no ac_cv_prog_gcc=no
@ -1276,7 +1302,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS" ac_save_CFLAGS="$CFLAGS"
CFLAGS= CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:1280: checking whether ${CC-cc} accepts -g" >&5 echo "configure:1306: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"\${ac_cv_prog_cc_g+set}\" = set"; then if eval "test \"\${ac_cv_prog_cc_g+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1310,7 +1336,7 @@ fi
# Extract the first word of "ranlib", so it can be a program name with args. # Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2 set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1314: checking for $ac_word" >&5 echo "configure:1340: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_RANLIB+set}\" = set"; then if eval "test \"\${ac_cv_prog_RANLIB+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1345,7 +1371,7 @@ if test "x$ac_cv_prog_gcc" = xyes; then
STAGE1_CFLAGS="-O2" STAGE1_CFLAGS="-O2"
GRUB_CFLAGS="-O2" GRUB_CFLAGS="-O2"
echo $ac_n "checking whether optimization for size works""... $ac_c" 1>&6 echo $ac_n "checking whether optimization for size works""... $ac_c" 1>&6
echo "configure:1349: checking whether optimization for size works" >&5 echo "configure:1375: checking whether optimization for size works" >&5
if eval "test \"\${size_flag+set}\" = set"; then if eval "test \"\${size_flag+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1353,14 +1379,14 @@ else
saved_CFLAGS=$CFLAGS saved_CFLAGS=$CFLAGS
CFLAGS="-Os -g" CFLAGS="-Os -g"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1357 "configure" #line 1383 "configure"
#include "confdefs.h" #include "confdefs.h"
int main() { int main() {
; return 0; } ; return 0; }
EOF EOF
if { (eval echo configure:1364: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then if { (eval echo configure:1390: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest* rm -rf conftest*
size_flag=yes size_flag=yes
else else
@ -1393,7 +1419,7 @@ CPPFLAGS="$CPPFLAGS -Wall -Wmissing-prototypes -Wunused"
# Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args. # Extract the first word of "${ac_tool_prefix}ld", so it can be a program name with args.
set dummy ${ac_tool_prefix}ld; ac_word=$2 set dummy ${ac_tool_prefix}ld; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1397: checking for $ac_word" >&5 echo "configure:1423: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_LD+set}\" = set"; then if eval "test \"\${ac_cv_prog_LD+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1425,7 +1451,7 @@ fi
# Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args. # Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args.
set dummy ${ac_tool_prefix}objcopy; ac_word=$2 set dummy ${ac_tool_prefix}objcopy; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1429: checking for $ac_word" >&5 echo "configure:1455: checking for $ac_word" >&5
if eval "test \"\${ac_cv_prog_OBJCOPY+set}\" = set"; then if eval "test \"\${ac_cv_prog_OBJCOPY+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1458,7 +1484,7 @@ fi
# Defined in acinclude.m4. # Defined in acinclude.m4.
echo $ac_n "checking if C symbols get an underscore after compilation""... $ac_c" 1>&6 echo $ac_n "checking if C symbols get an underscore after compilation""... $ac_c" 1>&6
echo "configure:1462: checking if C symbols get an underscore after compilation" >&5 echo "configure:1488: checking if C symbols get an underscore after compilation" >&5
if eval "test \"\${grub_cv_asm_uscore+set}\" = set"; then if eval "test \"\${grub_cv_asm_uscore+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1471,7 +1497,7 @@ func (int *list)
} }
EOF EOF
if { ac_try='${CC-cc} -S conftest.c'; { (eval echo configure:1475: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.s; then : if { ac_try='${CC-cc} -S conftest.c'; { (eval echo configure:1501: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.s; then :
else else
{ echo "configure: error: ${CC-cc} failed to produce assembly code" 1>&2; exit 1; } { echo "configure: error: ${CC-cc} failed to produce assembly code" 1>&2; exit 1; }
fi fi
@ -1493,7 +1519,7 @@ fi
echo "$ac_t""$grub_cv_asm_uscore" 1>&6 echo "$ac_t""$grub_cv_asm_uscore" 1>&6
echo $ac_n "checking whether ${OBJCOPY} works for absolute addresses""... $ac_c" 1>&6 echo $ac_n "checking whether ${OBJCOPY} works for absolute addresses""... $ac_c" 1>&6
echo "configure:1497: checking whether ${OBJCOPY} works for absolute addresses" >&5 echo "configure:1523: checking whether ${OBJCOPY} works for absolute addresses" >&5
if eval "test \"\${grub_cv_prog_objcopy_absolute+set}\" = set"; then if eval "test \"\${grub_cv_prog_objcopy_absolute+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1505,21 +1531,21 @@ blah (void)
} }
EOF EOF
if { (eval echo configure:1509: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then : if { (eval echo configure:1535: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then :
else else
{ echo "configure: error: ${CC-cc} cannot compile C source code" 1>&2; exit 1; } { echo "configure: error: ${CC-cc} cannot compile C source code" 1>&2; exit 1; }
fi fi
grub_cv_prog_objcopy_absolute=yes grub_cv_prog_objcopy_absolute=yes
for link_addr in 2000 8000 7C00; do for link_addr in 2000 8000 7C00; do
if { ac_try='${LD-ld} -N -Ttext $link_addr conftest.o -o conftest.exec'; { (eval echo configure:1515: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : if { ac_try='${LD-ld} -N -Ttext $link_addr conftest.o -o conftest.exec'; { (eval echo configure:1541: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then :
else else
{ echo "configure: error: ${LD-ld} cannot link at address $link_addr" 1>&2; exit 1; } { echo "configure: error: ${LD-ld} cannot link at address $link_addr" 1>&2; exit 1; }
fi fi
if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'; { (eval echo configure:1519: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then : if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'; { (eval echo configure:1545: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then :
else else
{ echo "configure: error: ${OBJCOPY-objcopy} cannot create binary files" 1>&2; exit 1; } { echo "configure: error: ${OBJCOPY-objcopy} cannot create binary files" 1>&2; exit 1; }
fi fi
if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'; { (eval echo configure:1523: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'; { (eval echo configure:1549: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then
mv -f conftest conftest.old mv -f conftest conftest.old
else else
grub_cv_prog_objcopy_absolute=no grub_cv_prog_objcopy_absolute=no
@ -1536,7 +1562,7 @@ fi
echo $ac_n "checking for .code16 addr32 assembler support""... $ac_c" 1>&6 echo $ac_n "checking for .code16 addr32 assembler support""... $ac_c" 1>&6
echo "configure:1540: checking for .code16 addr32 assembler support" >&5 echo "configure:1566: checking for .code16 addr32 assembler support" >&5
if eval "test \"\${grub_cv_asm_addr32+set}\" = set"; then if eval "test \"\${grub_cv_asm_addr32+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1546,7 +1572,7 @@ l1: addr32
movb %al, l1 movb %al, l1
EOF EOF
if { ac_try='${CC-cc} -c conftest.s'; { (eval echo configure:1550: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then if { ac_try='${CC-cc} -c conftest.s'; { (eval echo configure:1576: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then
grub_cv_asm_addr32=yes grub_cv_asm_addr32=yes
else else
grub_cv_asm_addr32=no grub_cv_asm_addr32=no
@ -1561,7 +1587,7 @@ fi
echo $ac_n "checking whether addr32 must be in the same line as the instruction""... $ac_c" 1>&6 echo $ac_n "checking whether addr32 must be in the same line as the instruction""... $ac_c" 1>&6
echo "configure:1565: checking whether addr32 must be in the same line as the instruction" >&5 echo "configure:1591: checking whether addr32 must be in the same line as the instruction" >&5
if eval "test \"\${grub_cv_asm_prefix_requirement+set}\" = set"; then if eval "test \"\${grub_cv_asm_prefix_requirement+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
@ -1570,7 +1596,7 @@ else
l1: addr32 movb %al, l1 l1: addr32 movb %al, l1
EOF EOF
if { ac_try='${CC-cc} -c conftest.s'; { (eval echo configure:1574: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then if { ac_try='${CC-cc} -c conftest.s'; { (eval echo configure:1600: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then
grub_cv_asm_prefix_requirement=yes grub_cv_asm_prefix_requirement=yes
else else
grub_cv_asm_prefix_requirement=no grub_cv_asm_prefix_requirement=no
@ -1601,7 +1627,7 @@ fi
# Check for curses libraries. # Check for curses libraries.
echo $ac_n "checking for wgetch in -lncurses""... $ac_c" 1>&6 echo $ac_n "checking for wgetch in -lncurses""... $ac_c" 1>&6
echo "configure:1605: checking for wgetch in -lncurses" >&5 echo "configure:1631: checking for wgetch in -lncurses" >&5
ac_lib_var=`echo ncurses'_'wgetch | sed 'y%./+-:%__p__%'` ac_lib_var=`echo ncurses'_'wgetch | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
@ -1609,7 +1635,7 @@ else
ac_save_LIBS="$LIBS" ac_save_LIBS="$LIBS"
LIBS="-lncurses $LIBS" LIBS="-lncurses $LIBS"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1613 "configure" #line 1639 "configure"
#include "confdefs.h" #include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */ /* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2 /* We use char because int might match the return type of a gcc2
@ -1620,7 +1646,7 @@ int main() {
wgetch() wgetch()
; return 0; } ; return 0; }
EOF EOF
if { (eval echo configure:1624: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then if { (eval echo configure:1650: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest* rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes" eval "ac_cv_lib_$ac_lib_var=yes"
else else
@ -1643,7 +1669,7 @@ EOF
else else
echo "$ac_t""no" 1>&6 echo "$ac_t""no" 1>&6
echo $ac_n "checking for wgetch in -lcurses""... $ac_c" 1>&6 echo $ac_n "checking for wgetch in -lcurses""... $ac_c" 1>&6
echo "configure:1647: checking for wgetch in -lcurses" >&5 echo "configure:1673: checking for wgetch in -lcurses" >&5
ac_lib_var=`echo curses'_'wgetch | sed 'y%./+-:%__p__%'` ac_lib_var=`echo curses'_'wgetch | sed 'y%./+-:%__p__%'`
if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then if eval "test \"\${ac_cv_lib_$ac_lib_var+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
@ -1651,7 +1677,7 @@ else
ac_save_LIBS="$LIBS" ac_save_LIBS="$LIBS"
LIBS="-lcurses $LIBS" LIBS="-lcurses $LIBS"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1655 "configure" #line 1681 "configure"
#include "confdefs.h" #include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */ /* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2 /* We use char because int might match the return type of a gcc2
@ -1662,7 +1688,7 @@ int main() {
wgetch() wgetch()
; return 0; } ; return 0; }
EOF EOF
if { (eval echo configure:1666: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then if { (eval echo configure:1692: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest* rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes" eval "ac_cv_lib_$ac_lib_var=yes"
else else
@ -1692,7 +1718,7 @@ fi
# Check for headers. # Check for headers.
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:1696: checking how to run the C preprocessor" >&5 echo "configure:1722: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory. # On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then if test -n "$CPP" && test -d "$CPP"; then
CPP= CPP=
@ -1707,13 +1733,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser, # On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp. # not just through cpp.
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1711 "configure" #line 1737 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <assert.h> #include <assert.h>
Syntax Error Syntax Error
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1717: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:1743: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
: :
@ -1724,13 +1750,13 @@ else
rm -rf conftest* rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp" CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1728 "configure" #line 1754 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <assert.h> #include <assert.h>
Syntax Error Syntax Error
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1734: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:1760: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
: :
@ -1741,13 +1767,13 @@ else
rm -rf conftest* rm -rf conftest*
CPP="${CC-cc} -nologo -E" CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1745 "configure" #line 1771 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <assert.h> #include <assert.h>
Syntax Error Syntax Error
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1751: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:1777: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
: :
@ -1775,17 +1801,17 @@ for ac_hdr in string.h strings.h ncurses/curses.h ncurses.h curses.h
do do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:1779: checking for $ac_hdr" >&5 echo "configure:1805: checking for $ac_hdr" >&5
if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then if eval "test \"\${ac_cv_header_$ac_safe+set}\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6 echo $ac_n "(cached) $ac_c" 1>&6
else else
cat > conftest.$ac_ext <<EOF cat > conftest.$ac_ext <<EOF
#line 1784 "configure" #line 1810 "configure"
#include "confdefs.h" #include "confdefs.h"
#include <$ac_hdr> #include <$ac_hdr>
EOF EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1789: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } { (eval echo configure:1815: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then if test -z "$ac_err"; then
rm -rf conftest* rm -rf conftest*
@ -1859,6 +1885,17 @@ if test x"$enable_minix" != xno; then
FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_MINIX=1" FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_MINIX=1"
fi fi
# Check whether --enable-tftp or --disable-tftp was given.
if test "${enable_tftp+set}" = set; then
enableval="$enable_tftp"
:
fi
if test x"$enable_tftp" = xyes; then
FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_TFTP=1"
fi
# Check whether --enable-gunzip or --disable-gunzip was given. # Check whether --enable-gunzip or --disable-gunzip was given.
if test "${enable_gunzip+set}" = set; then if test "${enable_gunzip+set}" = set; then
enableval="$enable_gunzip" enableval="$enable_gunzip"
@ -1872,6 +1909,144 @@ fi
# Check whether --enable-ne or --disable-ne was given.
if test "${enable_ne+set}" = set; then
enableval="$enable_ne"
:
fi
if test x"$enable_ne" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NE=1"
fi
# Check whether --enable-nepci or --disable-nepci was given.
if test "${enable_nepci+set}" = set; then
enableval="$enable_nepci"
:
fi
if test x"$enable_nepci" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NEPCI=1"
fi
# Check whether --enable-wd or --disable-wd was given.
if test "${enable_wd+set}" = set; then
enableval="$enable_wd"
:
fi
if test x"$enable_wd" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_WD=1"
fi
# Check whether --enable-t503 or --disable-t503 was given.
if test "${enable_t503+set}" = set; then
enableval="$enable_t503"
:
fi
if test x"$enable_t503" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_T503=1"
fi
# Check whether --enable-t509 or --disable-t509 was given.
if test "${enable_t509+set}" = set; then
enableval="$enable_t509"
:
fi
if test x"$enable_t509" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_T509=1"
fi
# Check whether --enable-3c59x or --disable-3c59x was given.
if test "${enable_3c59x+set}" = set; then
enableval="$enable_3c59x"
:
fi
if test x"$enable_3c59x" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C59X=1"
fi
# Check whether --enable-lance or --disable-lance was given.
if test "${enable_lance+set}" = set; then
enableval="$enable_lance"
:
fi
if test x"$enable_lance" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_LANCE=1"
fi
# Check whether --enable-cs or --disable-cs was given.
if test "${enable_cs+set}" = set; then
enableval="$enable_cs"
:
fi
if test x"$enable_cs" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_CS=1"
fi
# Check whether --enable-eepro100 or --disable-eepro100 was given.
if test "${enable_eepro100+set}" = set; then
enableval="$enable_eepro100"
:
fi
if test x"$enable_eepro100" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_EEPRO100=1"
fi
if test ! -z "$NET_CFLAGS"; then
NETBOOT_SUPPORT_TRUE=
NETBOOT_SUPPORT_FALSE='#'
else
NETBOOT_SUPPORT_TRUE='#'
NETBOOT_SUPPORT_FALSE=
fi
# Check whether --enable-ne-scan or --disable-ne-scan was given.
if test "${enable_ne_scan+set}" = set; then
enableval="$enable_ne_scan"
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DNE_SCAN=$enable_ne_scan"
else
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DNE_SCAN=0x280,0x300,0x320,0x340"
fi
# Check whether --enable-wd-default-mem or --disable-wd-default-mem was given.
if test "${enable_wd_default_mem+set}" = set; then
enableval="$enable_wd_default_mem"
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DWD_DEFAULT_MEM=$enable_wd_default_mem"
else
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DWD_DEFAULT_MEM=0xCC000"
fi
# Check whether --enable-cs-scan or --disable-cs-scan was given.
if test "${enable_cs_scan+set}" = set; then
enableval="$enable_cs_scan"
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCS_SCAN=$enable_cs_scan"
fi
# Output. # Output.
trap '' 1 2 15 trap '' 1 2 15
@ -1976,7 +2151,7 @@ ac_given_srcdir=$srcdir
ac_given_INSTALL="$INSTALL" ac_given_INSTALL="$INSTALL"
trap 'rm -fr `echo "Makefile stage1/Makefile stage2/Makefile docs/Makefile \ trap 'rm -fr `echo "Makefile stage1/Makefile stage2/Makefile docs/Makefile \
debian/Makefile grub/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 debian/Makefile grub/Makefile netboot/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF EOF
cat >> $CONFIG_STATUS <<EOF cat >> $CONFIG_STATUS <<EOF
@ -2047,6 +2222,10 @@ s%@OBJCOPY@%$OBJCOPY%g
s%@GRUB_LIBS@%$GRUB_LIBS%g s%@GRUB_LIBS@%$GRUB_LIBS%g
s%@CPP@%$CPP%g s%@CPP@%$CPP%g
s%@FSYS_CFLAGS@%$FSYS_CFLAGS%g s%@FSYS_CFLAGS@%$FSYS_CFLAGS%g
s%@NET_CFLAGS@%$NET_CFLAGS%g
s%@NETBOOT_SUPPORT_TRUE@%$NETBOOT_SUPPORT_TRUE%g
s%@NETBOOT_SUPPORT_FALSE@%$NETBOOT_SUPPORT_FALSE%g
s%@NET_EXTRAFLAGS@%$NET_EXTRAFLAGS%g
CEOF CEOF
EOF EOF
@ -2089,7 +2268,7 @@ EOF
cat >> $CONFIG_STATUS <<EOF cat >> $CONFIG_STATUS <<EOF
CONFIG_FILES=\${CONFIG_FILES-"Makefile stage1/Makefile stage2/Makefile docs/Makefile \ CONFIG_FILES=\${CONFIG_FILES-"Makefile stage1/Makefile stage2/Makefile docs/Makefile \
debian/Makefile grub/Makefile"} debian/Makefile grub/Makefile netboot/Makefile"}
EOF EOF
cat >> $CONFIG_STATUS <<\EOF cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then

View file

@ -147,6 +147,13 @@ if test x"$enable_minix" != xno; then
FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_MINIX=1" FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_MINIX=1"
fi fi
AC_ARG_ENABLE(tftp,
[ --enable-tftp enable TFTP support in Stage 2])
if test x"$enable_tftp" = xyes; then
FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_TFTP=1"
fi
AC_ARG_ENABLE(gunzip, AC_ARG_ENABLE(gunzip,
[ --disable-gunzip disable decompression in Stage 2]) [ --disable-gunzip disable decompression in Stage 2])
@ -156,7 +163,90 @@ fi
AC_SUBST(FSYS_CFLAGS) AC_SUBST(FSYS_CFLAGS)
AC_ARG_ENABLE(ne,
[ --enable-ne enable NE1000/2000 network driver in Stage 2])
if test x"$enable_ne" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NE=1"
fi
AC_ARG_ENABLE(nepci,
[ --enable-nepci enable PCI NE2000 network driver in Stage 2])
if test x"$enable_nepci" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NEPCI=1"
fi
AC_ARG_ENABLE(wd,
[ --enable-wd enable WD/SMC network driver in Stage 2])
if test x"$enable_wd" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_WD=1"
fi
AC_ARG_ENABLE(t503,
[ --enable-t503 enable 3C503 network driver in Stage 2])
if test x"$enable_t503" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_T503=1"
fi
AC_ARG_ENABLE(t509,
[ --enable-t509 enable 3C509 network driver in Stage 2])
if test x"$enable_t509" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_T509=1"
fi
AC_ARG_ENABLE(3c59x,
[ --enable-3c59x enable 3C59x network driver in Stage 2])
if test x"$enable_3c59x" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C59X=1"
fi
AC_ARG_ENABLE(lance,
[ --enable-lance enable LANCE network driver in Stage 2])
if test x"$enable_lance" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_LANCE=1"
fi
AC_ARG_ENABLE(cs,
[ --enable-cs enable CS89*0 network driver in Stage 2])
if test x"$enable_cs" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_CS=1"
fi
AC_ARG_ENABLE(eepro100,
[ --enable-eepro100 enable EtherExpress100 network driver in Stage 2])
if test x"$enable_eepro100" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_EEPRO100=1"
fi
AC_SUBST(NET_CFLAGS)
AM_CONDITIONAL(NETBOOT_SUPPORT, test ! -z "$NET_CFLAGS")
AC_ARG_ENABLE(ne-scan,
[ --enable-ne-scan set the parameter for NE network driver],
[NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DNE_SCAN=$enable_ne_scan"],
[NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DNE_SCAN=0x280,0x300,0x320,0x340"])
AC_ARG_ENABLE(wd-default-mem,
[ --enable-wd-default-mem set the parameter for WD network driver],
[NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DWD_DEFAULT_MEM=$enable_wd_default_mem"],
[NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DWD_DEFAULT_MEM=0xCC000"])
AC_ARG_ENABLE(cs-scan,
[ --enable-cs-scan set the parameter for CS network driver],
[NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCS_SCAN=$enable_cs_scan"])
AC_SUBST(NET_EXTRAFLAGS)
# Output. # Output.
AC_OUTPUT([Makefile stage1/Makefile stage2/Makefile docs/Makefile \ AC_OUTPUT([Makefile stage1/Makefile stage2/Makefile docs/Makefile \
debian/Makefile grub/Makefile]) debian/Makefile grub/Makefile netboot/Makefile])

2
debian/Makefile.in vendored
View file

@ -69,6 +69,8 @@ GRUB_LIBS = @GRUB_LIBS@
LD = @LD@ LD = @LD@
MAINT = @MAINT@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
NET_CFLAGS = @NET_CFLAGS@
NET_EXTRAFLAGS = @NET_EXTRAFLAGS@
OBJCOPY = @OBJCOPY@ OBJCOPY = @OBJCOPY@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
PERL = @PERL@ PERL = @PERL@

View file

@ -1,3 +1 @@
*.info* *.info*
version.texi
stamp-vti

View file

@ -69,6 +69,8 @@ GRUB_LIBS = @GRUB_LIBS@
LD = @LD@ LD = @LD@
MAINT = @MAINT@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
NET_CFLAGS = @NET_CFLAGS@
NET_EXTRAFLAGS = @NET_EXTRAFLAGS@
OBJCOPY = @OBJCOPY@ OBJCOPY = @OBJCOPY@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
PERL = @PERL@ PERL = @PERL@

3
docs/stamp-vti Normal file
View file

@ -0,0 +1,3 @@
@set UPDATED 10 September 1999
@set EDITION 0.5.93
@set VERSION 0.5.93

3
docs/version.texi Normal file
View file

@ -0,0 +1,3 @@
@set UPDATED 10 September 1999
@set EDITION 0.5.93
@set VERSION 0.5.93

View file

@ -69,6 +69,8 @@ GRUB_LIBS = @GRUB_LIBS@
LD = @LD@ LD = @LD@
MAINT = @MAINT@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
NET_CFLAGS = @NET_CFLAGS@
NET_EXTRAFLAGS = @NET_EXTRAFLAGS@
OBJCOPY = @OBJCOPY@ OBJCOPY = @OBJCOPY@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
PERL = @PERL@ PERL = @PERL@

574
netboot/3c509.c Normal file
View file

@ -0,0 +1,574 @@
/**************************************************************************
NETBOOT - BOOTP/TFTP Bootstrap Program
Author: Martin Renters.
Date: Mar 22 1995
This code is based heavily on David Greenman's if_ed.c driver and
Andres Vega Garcia's if_ep.c driver.
Copyright (C) 1993-1994, David Greenman, Martin Renters.
Copyright (C) 1993-1995, Andres Vega Garcia.
Copyright (C) 1995, Serge Babkin.
This software may be used, modified, copied, distributed, and sold, in
both source and binary form provided that the above copyright and these
terms are retained. Under no circumstances are the authors responsible for
the proper functioning of this software, nor do the authors assume any
responsibility for damages incurred with its use.
3c509 support added by Serge Babkin (babkin@hq.icb.chel.su)
$Id$
***************************************************************************/
#ifdef INCLUDE_T509
/* #define EDEBUG */
#include "netboot.h"
#include "nic.h"
#include "3c509.h"
static unsigned char eth_vendor, eth_flags, eth_laar;
static unsigned short eth_nic_base, eth_asic_base;
static char bnc=0, utp=0; /* for 3C509 */
static void safetwiddle()
{
static int count=0;
static int count2=0;
static char tiddles[]="-\\|/";
putchar(tiddles[(count2++)&0xfff?count&3:(count++)&3]);
putchar('\b');
}
/* a surrogate */
static void DELAY(int val)
{
int c;
for(c=0; c<val; c+=20) {
twiddle();
}
}
static void SAFEDELAY(int val)
{
int c;
for (c=0; c<val; c+=20) {
safetwiddle();
}
}
/**************************************************************************
ETH_RESET - Reset adapter
***************************************************************************/
static void t509_reset(struct nic *nic)
{
int i;
/***********************************************************
Reset 3Com 509 card
*************************************************************/
if (eth_vendor != VENDOR_3C509)
return;
/* stop card */
outw(BASE + EP_COMMAND, RX_DISABLE);
outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
outw(BASE + EP_COMMAND, TX_DISABLE);
outw(BASE + EP_COMMAND, STOP_TRANSCEIVER);
outw(BASE + EP_COMMAND, RX_RESET);
outw(BASE + EP_COMMAND, TX_RESET);
outw(BASE + EP_COMMAND, C_INTR_LATCH);
outw(BASE + EP_COMMAND, SET_RD_0_MASK);
outw(BASE + EP_COMMAND, SET_INTR_MASK);
outw(BASE + EP_COMMAND, SET_RX_FILTER);
/*
* initialize card
*/
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
GO_WINDOW(0);
/* Disable the card */
outw(BASE + EP_W0_CONFIG_CTRL, 0);
/* Configure IRQ to none */
outw(BASE + EP_W0_RESOURCE_CFG, SET_IRQ(0));
/* Enable the card */
outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ);
GO_WINDOW(2);
/* Reload the ether_addr. */
for (i = 0; i < ETHER_ADDR_SIZE; i++)
outb(BASE + EP_W2_ADDR_0 + i, nic->node_addr[i]);
outw(BASE + EP_COMMAND, RX_RESET);
outw(BASE + EP_COMMAND, TX_RESET);
/* Window 1 is operating window */
GO_WINDOW(1);
for (i = 0; i < 31; i++)
inb(BASE + EP_W1_TX_STATUS);
/* get rid of stray intr's */
outw(BASE + EP_COMMAND, ACK_INTR | 0xff);
outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS);
outw(BASE + EP_COMMAND, SET_INTR_MASK);
outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL |
FIL_BRDCST);
/* configure BNC */
if (bnc) {
outw(BASE + EP_COMMAND, START_TRANSCEIVER);
SAFEDELAY(1000);
}
/* configure UTP */
if (utp) {
GO_WINDOW(4);
outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP);
GO_WINDOW(1);
}
/* start tranciever and receiver */
outw(BASE + EP_COMMAND, RX_ENABLE);
outw(BASE + EP_COMMAND, TX_ENABLE);
/* set early threshold for minimal packet length */
outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | ETH_MIN_PACKET);
outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16);
}
/**************************************************************************
ETH_TRANSMIT - Transmit a frame
***************************************************************************/
static char padmap[] = {
0, 3, 2, 1};
static void t509_transmit(
struct nic *nic,
char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
{
register u_int len;
int pad;
int status;
if(eth_vendor != VENDOR_3C509)
return;
#ifdef EDEBUG
printf("{l=%d,t=%x}",s+ETHER_HDR_SIZE,t);
#endif
/* swap bytes of type */
t= htons(t);
len=s+ETHER_HDR_SIZE; /* actual length of packet */
pad = padmap[len & 3];
/*
* The 3c509 automatically pads short packets to minimum ethernet length,
* but we drop packets that are too large. Perhaps we should truncate
* them instead?
*/
if (len + pad > ETH_MAX_PACKET) {
return;
}
/* drop acknowledgements */
while(( status=inb(BASE + EP_W1_TX_STATUS) )& TXS_COMPLETE ) {
if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
outw(BASE + EP_COMMAND, TX_RESET);
outw(BASE + EP_COMMAND, TX_ENABLE);
}
outb(BASE + EP_W1_TX_STATUS, 0x0);
}
while (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) {
/* no room in FIFO */
}
outw(BASE + EP_W1_TX_PIO_WR_1, len);
outw(BASE + EP_W1_TX_PIO_WR_1, 0x0); /* Second dword meaningless */
/* write packet */
outsw(BASE + EP_W1_TX_PIO_WR_1, d, ETHER_ADDR_SIZE/2);
outsw(BASE + EP_W1_TX_PIO_WR_1, nic->node_addr, ETHER_ADDR_SIZE/2);
outw(BASE + EP_W1_TX_PIO_WR_1, t);
outsw(BASE + EP_W1_TX_PIO_WR_1, p, s / 2);
if (s & 1)
outb(BASE + EP_W1_TX_PIO_WR_1, *(p+s - 1));
while (pad--)
outb(BASE + EP_W1_TX_PIO_WR_1, 0); /* Padding */
/* timeout after sending */
DELAY(1000);
}
/**************************************************************************
ETH_POLL - Wait for a frame
***************************************************************************/
static int t509_poll(struct nic *nic)
{
/* common variables */
unsigned short type = 0; /* used by EDEBUG */
/* variables for 3C509 */
short status, cst;
register short rx_fifo;
if(eth_vendor!=VENDOR_3C509)
return 0;
cst=inw(BASE + EP_STATUS);
#ifdef EDEBUG
if(cst & 0x1FFF)
printf("-%x-",cst);
#endif
if( (cst & S_RX_COMPLETE)==0 ) {
/* acknowledge everything */
outw(BASE + EP_COMMAND, ACK_INTR| (cst & S_5_INTS));
outw(BASE + EP_COMMAND, C_INTR_LATCH);
return 0;
}
status = inw(BASE + EP_W1_RX_STATUS);
#ifdef EDEBUG
printf("*%x*",status);
#endif
if (status & ERR_RX) {
outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
return 0;
}
rx_fifo = status & RX_BYTES_MASK;
if (rx_fifo==0)
return 0;
/* read packet */
#ifdef EDEBUG
printf("[l=%d",rx_fifo);
#endif
insw(BASE + EP_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
if(rx_fifo & 1)
nic->packet[rx_fifo-1]=inb(BASE + EP_W1_RX_PIO_RD_1);
nic->packetlen=rx_fifo;
while(1) {
status = inw(BASE + EP_W1_RX_STATUS);
#ifdef EDEBUG
printf("*%x*",status);
#endif
rx_fifo = status & RX_BYTES_MASK;
if(rx_fifo>0) {
insw(BASE + EP_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
if(rx_fifo & 1)
nic->packet[nic->packetlen+rx_fifo-1]=inb(BASE + EP_W1_RX_PIO_RD_1);
nic->packetlen+=rx_fifo;
#ifdef EDEBUG
printf("+%d",rx_fifo);
#endif
}
if(( status & RX_INCOMPLETE )==0) {
#ifdef EDEBUG
printf("=%d",nic->packetlen);
#endif
break;
}
DELAY(1000);
}
/* acknowledge reception of packet */
outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
#ifdef EDEBUG
type = (nic->packet[12]<<8) | nic->packet[13];
if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
nic->packet[5] == 0xFF*ETHER_ADDR_SIZE)
printf(",t=0x%x,b]",type);
else
printf(",t=0x%x]",type);
#endif
return 1;
}
/*************************************************************************
3Com 509 - specific routines
**************************************************************************/
static int
eeprom_rdy()
{
int i;
for (i = 0; is_eeprom_busy(IS_BASE) && i < MAX_EEPROMBUSY; i++);
if (i >= MAX_EEPROMBUSY) {
/* printf("3c509: eeprom failed to come ready.\r\n"); */
printf("3c509: eeprom is busy.\r\n"); /* memory in EPROM is tight */
return (0);
}
return (1);
}
/*
* get_e: gets a 16 bits word from the EEPROM. we must have set the window
* before
*/
static int
get_e(offset)
int offset;
{
if (!eeprom_rdy())
return (0xffff);
outw(IS_BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset);
if (!eeprom_rdy())
return (0xffff);
return (inw(IS_BASE + EP_W0_EEPROM_DATA));
}
static int
send_ID_sequence(port)
int port;
{
int cx, al;
for (al = 0xff, cx = 0; cx < 255; cx++) {
outb(port, al);
al <<= 1;
if (al & 0x100)
al ^= 0xcf;
}
return (1);
}
/*
* We get eeprom data from the id_port given an offset into the eeprom.
* Basically; after the ID_sequence is sent to all of the cards; they enter
* the ID_CMD state where they will accept command requests. 0x80-0xbf loads
* the eeprom data. We then read the port 16 times and with every read; the
* cards check for contention (ie: if one card writes a 0 bit and another
* writes a 1 bit then the host sees a 0. At the end of the cycle; each card
* compares the data on the bus; if there is a difference then that card goes
* into ID_WAIT state again). In the meantime; one bit of data is returned in
* the AX register which is conveniently returned to us by inb(). Hence; we
* read 16 times getting one bit of data with each read.
*/
static int
get_eeprom_data(id_port, offset)
int id_port;
int offset;
{
int i, data = 0;
outb(id_port, 0x80 + offset);
DELAY(1000);
for (i = 0; i < 16; i++)
data = (data << 1) | (inw(id_port) & 1);
return (data);
}
static void t509_disable(struct nic *nic)
{
}
/**************************************************************************
ETH_PROBE - Look for an adapter
***************************************************************************/
struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
{
/* common variables */
int i;
int failcount;
/* variables for 3C509 */
for (failcount=0; failcount<4000; failcount++) {
int data, j, io_base, id_port = EP_ID_PORT;
u_short k;
int ep_current_tag = EP_LAST_TAG + 1;
short *p;
id_port = EP_ID_PORT;
ep_current_tag = EP_LAST_TAG + 1;
eth_vendor = VENDOR_NONE;
/*********************************************************
Search for 3Com 509 card
***********************************************************/
/* Look for the EISA boards, leave them activated */
/* search for the first card, ignore all others */
for(j = 1; j < 16 && eth_vendor==VENDOR_NONE ; j++) {
io_base = (j * EP_EISA_START) | EP_EISA_W0;
if (inw(io_base + EP_W0_MFG_ID) != MFG_ID)
continue;
/* we must found 0x1f if the board is EISA configurated */
if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
continue;
/* Reset and Enable the card */
outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER);
SAFEDELAY(1000); /* we must wait at least 1 ms */
outb(io_base + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER);
/*
* Once activated, all the registers are mapped in the range
* x000 - x00F, where x is the slot number.
*/
eth_nic_base = j * EP_EISA_START;
eth_vendor = VENDOR_3C509;
}
ep_current_tag--;
/* Look for the ISA boards. Init and leave them actived */
/* search for the first card, ignore all others */
outb(id_port, 0xc0); /* Global reset */
SAFEDELAY(1000);
for (i = 0; i < EP_MAX_BOARDS && eth_vendor==VENDOR_NONE; i++) {
outb(id_port, 0);
outb(id_port, 0);
send_ID_sequence(id_port);
data = get_eeprom_data(id_port, EEPROM_MFG_ID);
if (data != MFG_ID)
break;
/* resolve contention using the Ethernet address */
for (j = 0; j < 3; j++)
data = get_eeprom_data(id_port, j);
eth_nic_base =
(get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
outb(id_port, ep_current_tag); /* tags board */
outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG);
eth_vendor = VENDOR_3C509;
ep_current_tag--;
}
if(eth_vendor != VENDOR_3C509)
goto no3c509;
/*
* The iobase was found and MFG_ID was 0x6d50. PROD_ID should be
* 0x9[0-f]50
*/
GO_WINDOW(0);
k = get_e(EEPROM_PROD_ID);
if ((k & 0xf0ff) != (PROD_ID & 0xf0ff))
goto no3c509;
if(eth_nic_base >= EP_EISA_START) {
printf("3C5x9 board on EISA at 0x%x - ",eth_nic_base);
} else {
printf("3C5x9 board on ISA at 0x%x - ",eth_nic_base);
}
/* test for presence of connectors */
i = inw(IS_BASE + EP_W0_CONFIG_CTRL);
j = inw(IS_BASE + EP_W0_ADDRESS_CFG) >> 14;
switch(j) {
case 0:
if(i & IS_UTP) {
printf("10baseT\r\n");
utp=1;
}
else {
printf("10baseT not present\r\n");
eth_vendor=VENDOR_NONE;
goto no3c509;
}
break;
case 1:
if(i & IS_AUI)
printf("10base5\r\n");
else {
printf("10base5 not present\r\n");
eth_vendor=VENDOR_NONE;
goto no3c509;
}
break;
case 3:
if(i & IS_BNC) {
printf("10base2\r\n");
bnc=1;
}
else {
printf("10base2 not present\r\n");
eth_vendor=VENDOR_NONE;
goto no3c509;
}
break;
default:
printf("unknown connector\r\n");
eth_vendor=VENDOR_NONE;
goto no3c509;
}
/*
* Read the station address from the eeprom
*/
p = (u_short *) nic->node_addr;
for (i = 0; i < 3; i++) {
GO_WINDOW(0);
p[i] = htons(get_e(i));
GO_WINDOW(2);
outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i]));
}
printf("Ethernet address: ");
for(i=0; i<5; i++) {
printf("%b:",nic->node_addr[i]);
}
printf("%b\r\n",nic->node_addr[i]);
t509_reset(nic);
nic->reset = t509_reset;
nic->poll = t509_poll;
nic->transmit = t509_transmit;
nic->disable = t509_disable;
return nic;
no3c509:
eth_vendor = VENDOR_NONE;
printf("(probe fail)");
}
return 0;
}
#endif /* INCLUDE_T509 */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

389
netboot/3c509.h Normal file
View file

@ -0,0 +1,389 @@
/*
* Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. 2. The name
* of the author may not be used to endorse or promote products derived from
* this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* if_epreg.h,v 1.4 1994/11/13 10:12:37 gibbs Exp Modified by:
*
October 2, 1994
Modified by: Andres Vega Garcia
INRIA - Sophia Antipolis, France
e-mail: avega@sophia.inria.fr
finger: avega@pax.inria.fr
*/
/*
* Ethernet software status per interface.
*/
/*
* Some global constants
*/
#define TX_INIT_RATE 16
#define TX_INIT_MAX_RATE 64
#define RX_INIT_LATENCY 64
#define RX_INIT_EARLY_THRESH 64
#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */
#define MIN_RX_EARLY_THRESHL 4
#define EEPROMSIZE 0x40
#define MAX_EEPROMBUSY 1000
#define EP_LAST_TAG 0xd7
#define EP_MAX_BOARDS 16
#define EP_ID_PORT 0x100
/*
* some macros to acces long named fields
*/
#define IS_BASE (eth_nic_base)
#define BASE (eth_nic_base)
/*
* Commands to read/write EEPROM trough EEPROM command register (Window 0,
* Offset 0xa)
*/
#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */
#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */
#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */
#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */
#define EEPROM_BUSY (1<<15)
#define EEPROM_TST_MODE (1<<14)
/*
* Some short functions, worth to let them be a macro
*/
#define is_eeprom_busy(b) (inw((b)+EP_W0_EEPROM_COMMAND)&EEPROM_BUSY)
#define GO_WINDOW(x) outw(BASE+EP_COMMAND, WINDOW_SELECT|(x))
/**************************************************************************
* *
* These define the EEPROM data structure. They are used in the probe
* function to verify the existance of the adapter after having sent
* the ID_Sequence.
*
* There are others but only the ones we use are defined here.
*
**************************************************************************/
#define EEPROM_NODE_ADDR_0 0x0 /* Word */
#define EEPROM_NODE_ADDR_1 0x1 /* Word */
#define EEPROM_NODE_ADDR_2 0x2 /* Word */
#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */
#define EEPROM_MFG_ID 0x7 /* 0x6d50 */
#define EEPROM_ADDR_CFG 0x8 /* Base addr */
#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */
/**************************************************************************
* *
* These are the registers for the 3Com 3c509 and their bit patterns when *
* applicable. They have been taken out the the "EtherLink III Parallel *
* Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual *
* from 3com. *
* *
**************************************************************************/
#define EP_COMMAND 0x0e /* Write. BASE+0x0e is always a
* command reg. */
#define EP_STATUS 0x0e /* Read. BASE+0x0e is always status
* reg. */
#define EP_WINDOW 0x0f /* Read. BASE+0x0f is always window
* reg. */
/*
* Window 0 registers. Setup.
*/
/* Write */
#define EP_W0_EEPROM_DATA 0x0c
#define EP_W0_EEPROM_COMMAND 0x0a
#define EP_W0_RESOURCE_CFG 0x08
#define EP_W0_ADDRESS_CFG 0x06
#define EP_W0_CONFIG_CTRL 0x04
/* Read */
#define EP_W0_PRODUCT_ID 0x02
#define EP_W0_MFG_ID 0x00
/*
* Window 1 registers. Operating Set.
*/
/* Write */
#define EP_W1_TX_PIO_WR_2 0x02
#define EP_W1_TX_PIO_WR_1 0x00
/* Read */
#define EP_W1_FREE_TX 0x0c
#define EP_W1_TX_STATUS 0x0b /* byte */
#define EP_W1_TIMER 0x0a /* byte */
#define EP_W1_RX_STATUS 0x08
#define EP_W1_RX_PIO_RD_2 0x02
#define EP_W1_RX_PIO_RD_1 0x00
/*
* Window 2 registers. Station Address Setup/Read
*/
/* Read/Write */
#define EP_W2_ADDR_5 0x05
#define EP_W2_ADDR_4 0x04
#define EP_W2_ADDR_3 0x03
#define EP_W2_ADDR_2 0x02
#define EP_W2_ADDR_1 0x01
#define EP_W2_ADDR_0 0x00
/*
* Window 3 registers. FIFO Management.
*/
/* Read */
#define EP_W3_FREE_TX 0x0c
#define EP_W3_FREE_RX 0x0a
/*
* Window 4 registers. Diagnostics.
*/
/* Read/Write */
#define EP_W4_MEDIA_TYPE 0x0a
#define EP_W4_CTRLR_STATUS 0x08
#define EP_W4_NET_DIAG 0x06
#define EP_W4_FIFO_DIAG 0x04
#define EP_W4_HOST_DIAG 0x02
#define EP_W4_TX_DIAG 0x00
/*
* Window 5 Registers. Results and Internal status.
*/
/* Read */
#define EP_W5_READ_0_MASK 0x0c
#define EP_W5_INTR_MASK 0x0a
#define EP_W5_RX_FILTER 0x08
#define EP_W5_RX_EARLY_THRESH 0x06
#define EP_W5_TX_AVAIL_THRESH 0x02
#define EP_W5_TX_START_THRESH 0x00
/*
* Window 6 registers. Statistics.
*/
/* Read/Write */
#define TX_TOTAL_OK 0x0c
#define RX_TOTAL_OK 0x0a
#define TX_DEFERRALS 0x08
#define RX_FRAMES_OK 0x07
#define TX_FRAMES_OK 0x06
#define RX_OVERRUNS 0x05
#define TX_COLLISIONS 0x04
#define TX_AFTER_1_COLLISION 0x03
#define TX_AFTER_X_COLLISIONS 0x02
#define TX_NO_SQE 0x01
#define TX_CD_LOST 0x00
/****************************************
*
* Register definitions.
*
****************************************/
/*
* Command register. All windows.
*
* 16 bit register.
* 15-11: 5-bit code for command to be executed.
* 10-0: 11-bit arg if any. For commands with no args;
* this can be set to anything.
*/
#define GLOBAL_RESET (u_short) 0x0000 /* Wait at least 1ms
* after issuing */
#define WINDOW_SELECT (u_short) (0x1<<11)
#define START_TRANSCEIVER (u_short) (0x2<<11) /* Read ADDR_CFG reg to
* determine whether
* this is needed. If
* so; wait 800 uSec
* before using trans-
* ceiver. */
#define RX_DISABLE (u_short) (0x3<<11) /* state disabled on
* power-up */
#define RX_ENABLE (u_short) (0x4<<11)
#define RX_RESET (u_short) (0x5<<11)
#define RX_DISCARD_TOP_PACK (u_short) (0x8<<11)
#define TX_ENABLE (u_short) (0x9<<11)
#define TX_DISABLE (u_short) (0xa<<11)
#define TX_RESET (u_short) (0xb<<11)
#define REQ_INTR (u_short) (0xc<<11)
#define SET_INTR_MASK (u_short) (0xe<<11)
#define SET_RD_0_MASK (u_short) (0xf<<11)
#define SET_RX_FILTER (u_short) (0x10<<11)
#define FIL_INDIVIDUAL (u_short) (0x1)
#define FIL_GROUP (u_short) (0x2)
#define FIL_BRDCST (u_short) (0x4)
#define FIL_ALL (u_short) (0x8)
#define SET_RX_EARLY_THRESH (u_short) (0x11<<11)
#define SET_TX_AVAIL_THRESH (u_short) (0x12<<11)
#define SET_TX_START_THRESH (u_short) (0x13<<11)
#define STATS_ENABLE (u_short) (0x15<<11)
#define STATS_DISABLE (u_short) (0x16<<11)
#define STOP_TRANSCEIVER (u_short) (0x17<<11)
/*
* The following C_* acknowledge the various interrupts. Some of them don't
* do anything. See the manual.
*/
#define ACK_INTR (u_short) (0x6800)
#define C_INTR_LATCH (u_short) (ACK_INTR|0x1)
#define C_CARD_FAILURE (u_short) (ACK_INTR|0x2)
#define C_TX_COMPLETE (u_short) (ACK_INTR|0x4)
#define C_TX_AVAIL (u_short) (ACK_INTR|0x8)
#define C_RX_COMPLETE (u_short) (ACK_INTR|0x10)
#define C_RX_EARLY (u_short) (ACK_INTR|0x20)
#define C_INT_RQD (u_short) (ACK_INTR|0x40)
#define C_UPD_STATS (u_short) (ACK_INTR|0x80)
/*
* Status register. All windows.
*
* 15-13: Window number(0-7).
* 12: Command_in_progress.
* 11: reserved.
* 10: reserved.
* 9: reserved.
* 8: reserved.
* 7: Update Statistics.
* 6: Interrupt Requested.
* 5: RX Early.
* 4: RX Complete.
* 3: TX Available.
* 2: TX Complete.
* 1: Adapter Failure.
* 0: Interrupt Latch.
*/
#define S_INTR_LATCH (u_short) (0x1)
#define S_CARD_FAILURE (u_short) (0x2)
#define S_TX_COMPLETE (u_short) (0x4)
#define S_TX_AVAIL (u_short) (0x8)
#define S_RX_COMPLETE (u_short) (0x10)
#define S_RX_EARLY (u_short) (0x20)
#define S_INT_RQD (u_short) (0x40)
#define S_UPD_STATS (u_short) (0x80)
#define S_5_INTS (S_CARD_FAILURE|S_TX_COMPLETE|\
S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY)
#define S_COMMAND_IN_PROGRESS (u_short) (0x1000)
/*
* FIFO Registers.
* RX Status. Window 1/Port 08
*
* 15: Incomplete or FIFO empty.
* 14: 1: Error in RX Packet 0: Incomplete or no error.
* 13-11: Type of error.
* 1000 = Overrun.
* 1011 = Run Packet Error.
* 1100 = Alignment Error.
* 1101 = CRC Error.
* 1001 = Oversize Packet Error (>1514 bytes)
* 0010 = Dribble Bits.
* (all other error codes, no errors.)
*
* 10-0: RX Bytes (0-1514)
*/
#define ERR_RX_INCOMPLETE (u_short) (0x1<<15)
#define ERR_RX (u_short) (0x1<<14)
#define ERR_RX_OVERRUN (u_short) (0x8<<11)
#define ERR_RX_RUN_PKT (u_short) (0xb<<11)
#define ERR_RX_ALIGN (u_short) (0xc<<11)
#define ERR_RX_CRC (u_short) (0xd<<11)
#define ERR_RX_OVERSIZE (u_short) (0x9<<11)
#define ERR_RX_DRIBBLE (u_short) (0x2<<11)
/*
* FIFO Registers.
* TX Status. Window 1/Port 0B
*
* Reports the transmit status of a completed transmission. Writing this
* register pops the transmit completion stack.
*
* Window 1/Port 0x0b.
*
* 7: Complete
* 6: Interrupt on successful transmission requested.
* 5: Jabber Error (TP Only, TX Reset required. )
* 4: Underrun (TX Reset required. )
* 3: Maximum Collisions.
* 2: TX Status Overflow.
* 1-0: Undefined.
*
*/
#define TXS_COMPLETE 0x80
#define TXS_SUCCES_INTR_REQ 0x40
#define TXS_JABBER 0x20
#define TXS_UNDERRUN 0x10
#define TXS_MAX_COLLISION 0x8
#define TXS_STATUS_OVERFLOW 0x4
/*
* Configuration control register.
* Window 0/Port 04
*/
/* Read */
#define IS_AUI (1<<13)
#define IS_BNC (1<<12)
#define IS_UTP (1<<9)
/* Write */
#define ENABLE_DRQ_IRQ 0x0001
#define W0_P4_CMD_RESET_ADAPTER 0x4
#define W0_P4_CMD_ENABLE_ADAPTER 0x1
/*
* Media type and status.
* Window 4/Port 0A
*/
#define ENABLE_UTP 0xc0
#define DISABLE_UTP 0x0
/*
* Resource control register
*/
#define SET_IRQ(i) ( ((i)<<12) | 0xF00) /* set IRQ i */
/*
* Receive status register
*/
#define RX_BYTES_MASK (u_short) (0x07ff)
#define RX_ERROR 0x4000
#define RX_INCOMPLETE 0x8000
/*
* Misc defines for various things.
*/
#define ACTIVATE_ADAPTER_TO_CONFIG 0xff /* to the id_port */
#define MFG_ID 0x6d50 /* in EEPROM and W0 ADDR_CONFIG */
#define PROD_ID 0x9150
#define AUI 0x1
#define BNC 0x2
#define UTP 0x4
#define RX_BYTES_MASK (u_short) (0x07ff)
/* EISA support */
#define EP_EISA_START 0x1000
#define EP_EISA_W0 0x0c80
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

1172
netboot/3c59x.c Normal file

File diff suppressed because it is too large Load diff

20
netboot/Makefile.am Normal file
View file

@ -0,0 +1,20 @@
# For <stage1.h>.
INCLUDES = -I$(top_srcdir)/stage1
if NETBOOT_SUPPORT
LIBDRIVERS = libdrivers.a
else
LIBDRIVERS =
endif
noinst_LIBRARIES = $(LIBDRIVERS)
DRIVERS = 3c509.c 3c509.h 3c59x.c cs89x0.c cs89x0.h eepro100.c \
lance.c ns8390.c ns8390.h
libdrivers_a_SOURCES = byteorder.h config.c config.h fsys_tftp.c \
if.h io.h ip.c ip.h netboot.h netdevice.h nic.h pci.c pci.h \
$(DRIVERS)
libdrivers_a_CFLAGS = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-DFSYS_TFTP $(NET_CFLAGS) $(NET_EXTRAFLAGS)

536
netboot/Makefile.in Normal file
View file

@ -0,0 +1,536 @@
# Makefile.in generated automatically by automake 1.4a from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
SHELL = @SHELL@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
DESTDIR =
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_FLAG =
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
AMTAR = @AMTAR@
AMTARFLAGS = @AMTARFLAGS@
AWK = @AWK@
CC = @CC@
FSYS_CFLAGS = @FSYS_CFLAGS@
GRUB_CFLAGS = @GRUB_CFLAGS@
GRUB_LIBS = @GRUB_LIBS@
LD = @LD@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
NET_CFLAGS = @NET_CFLAGS@
NET_EXTRAFLAGS = @NET_EXTRAFLAGS@
OBJCOPY = @OBJCOPY@
PACKAGE = @PACKAGE@
PERL = @PERL@
RANLIB = @RANLIB@
STAGE1_CFLAGS = @STAGE1_CFLAGS@
STAGE2_CFLAGS = @STAGE2_CFLAGS@
VERSION = @VERSION@
host_cpu = @host_cpu@
host_vendor = @host_vendor@
install_sh = @install_sh@
# For <stage1.h>.
INCLUDES = -I$(top_srcdir)/stage1
@NETBOOT_SUPPORT_TRUE@LIBDRIVERS = @NETBOOT_SUPPORT_TRUE@libdrivers.a
@NETBOOT_SUPPORT_FALSE@LIBDRIVERS =
noinst_LIBRARIES = $(LIBDRIVERS)
DRIVERS = 3c509.c 3c509.h 3c59x.c cs89x0.c cs89x0.h eepro100.c \
lance.c ns8390.c ns8390.h
libdrivers_a_SOURCES = byteorder.h config.c config.h fsys_tftp.c \
if.h io.h ip.c ip.h netboot.h netdevice.h nic.h pci.c pci.h \
$(DRIVERS)
libdrivers_a_CFLAGS = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-DFSYS_TFTP $(NET_CFLAGS) $(NET_EXTRAFLAGS)
subdir = netboot
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir) -I..
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libdrivers_a_AR = $(AR) cru
libdrivers_a_LIBADD =
am_libdrivers_a_OBJECTS = libdrivers_a-config.o \
libdrivers_a-fsys_tftp.o libdrivers_a-ip.o libdrivers_a-pci.o \
libdrivers_a-3c509.o libdrivers_a-3c59x.o libdrivers_a-cs89x0.o \
libdrivers_a-eepro100.o libdrivers_a-lance.o libdrivers_a-ns8390.o
libdrivers_a_OBJECTS = $(am_libdrivers_a_OBJECTS)
AR = ar
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CFLAGS = @CFLAGS@
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(libdrivers_a_SOURCES)
DIST_COMMON = Makefile.am Makefile.in compile
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
GZIP_ENV = --best
DEP_FILES = .deps/3c509.P .deps/3c59x.P .deps/config.P .deps/cs89x0.P \
.deps/eepro100.P .deps/fsys_tftp.P .deps/ip.P .deps/lance.P \
.deps/ns8390.P .deps/pci.P
SOURCES = $(libdrivers_a_SOURCES)
OBJECTS = $(am_libdrivers_a_OBJECTS)
all: all-redirect
.SUFFIXES:
.SUFFIXES: .c .h .o
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu netboot/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES)
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
mostlyclean-compile:
-rm -f *.o core *.core
clean-compile:
distclean-compile:
-rm -f *.tab.c
maintainer-clean-compile:
libdrivers_a-config.o: config.c
libdrivers_a-fsys_tftp.o: fsys_tftp.c
libdrivers_a-ip.o: ip.c
libdrivers_a-pci.o: pci.c
libdrivers_a-3c509.o: 3c509.c
libdrivers_a-3c59x.o: 3c59x.c
libdrivers_a-cs89x0.o: cs89x0.c
libdrivers_a-eepro100.o: eepro100.c
libdrivers_a-lance.o: lance.c
libdrivers_a-ns8390.o: ns8390.c
libdrivers.a: $(libdrivers_a_OBJECTS) $(libdrivers_a_DEPENDENCIES)
-rm -f libdrivers.a
$(libdrivers_a_AR) libdrivers.a $(libdrivers_a_OBJECTS) $(libdrivers_a_LIBADD)
$(RANLIB) libdrivers.a
.c.o:
$(COMPILE) -c $<
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -f$$here/ID $$unique $(LISP)
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
|| etags $(ETAGS_ARGS) $$tags $$unique $(LISP)
mostlyclean-tags:
clean-tags:
distclean-tags:
-rm -f TAGS ID
maintainer-clean-tags:
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
distdir: $(DISTFILES)
here=`cd $(top_builddir) && pwd`; \
top_distdir=`cd $(top_distdir) && pwd`; \
distdir=`cd $(distdir) && pwd`; \
cd $(top_srcdir) \
&& $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu netboot/Makefile
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
DEPS_MAGIC := $(shell mkdir .deps > /dev/null 2>&1 || :)
-include $(DEP_FILES)
mostlyclean-depend:
clean-depend:
distclean-depend:
-rm -rf .deps
maintainer-clean-depend:
%.o: %.c
@echo '$(COMPILE) -c -o $@ $<'; \
$(COMPILE) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
%.lo: %.c
@echo '$(LTCOMPILE) -c -o $@ $<'; \
$(LTCOMPILE) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-config.o: config.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-config.lo: config.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-fsys_tftp.o: fsys_tftp.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-fsys_tftp.lo: fsys_tftp.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-ip.o: ip.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-ip.lo: ip.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-pci.o: pci.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-pci.lo: pci.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-3c509.o: 3c509.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-3c509.lo: 3c509.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-3c59x.o: 3c59x.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-3c59x.lo: 3c59x.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-cs89x0.o: cs89x0.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-cs89x0.lo: cs89x0.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-eepro100.o: eepro100.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-eepro100.lo: eepro100.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-lance.o: lance.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-lance.lo: lance.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
libdrivers_a-ns8390.o: ns8390.c
@echo '$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-cp .deps/$(*D)/$(*F).pp .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm .deps/$(*D)/$(*F).pp
libdrivers_a-ns8390.lo: ns8390.c
@echo '$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o $@ $<'; \
$(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -Wp,-MD,.deps/$(*D)/$(*F).pp -c -o $@ $<
@-sed -e 's/^\([^:]*\)\.o[ ]*:/\1.lo \1.o :/' \
< .deps/$(*D)/$(*F).pp > .deps/$(*D)/$(*F).P; \
tr ' ' '\012' < .deps/$(*D)/$(*F).pp \
| sed -e 's/^\\$$//' -e '/^$$/ d' -e '/:$$/ d' -e 's/$$/ :/' \
>> .deps/$(*D)/$(*F).P; \
rm -f .deps/$(*D)/$(*F).pp
info-am:
info: info-am
dvi-am:
dvi: dvi-am
check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
install-exec-am:
install-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install
installdirs:
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
mostlyclean-tags mostlyclean-depend mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-depend \
clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-tags distclean-depend distclean-generic \
clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
maintainer-clean-compile maintainer-clean-tags \
maintainer-clean-depend maintainer-clean-generic \
distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile tags mostlyclean-tags distclean-tags \
clean-tags maintainer-clean-tags distdir mostlyclean-depend \
distclean-depend clean-depend maintainer-clean-depend info-am info \
dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
install-exec install-data-am install-data install-am install \
uninstall-am uninstall all-redirect all-am all install-strip \
installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

77
netboot/byteorder.h Normal file
View file

@ -0,0 +1,77 @@
#ifndef _I386_BYTEORDER_H
#define _I386_BYTEORDER_H
/*
* This file contains parts of Linux's /usr/include/asm/byteorder.h
*/
#undef ntohl
#undef ntohs
#undef htonl
#undef htons
extern unsigned long int ntohl(unsigned long int);
extern unsigned short int ntohs(unsigned short int);
extern unsigned long int htonl(unsigned long int);
extern unsigned short int htons(unsigned short int);
extern __inline__ unsigned long int __ntohl(unsigned long int);
extern __inline__ unsigned short int __ntohs(unsigned short int);
extern __inline__ unsigned long int __constant_ntohl(unsigned long int);
extern __inline__ unsigned short int __constant_ntohs(unsigned short int);
extern __inline__ unsigned long int
__ntohl(unsigned long int x)
{
__asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
"rorl $16,%0\n\t" /* swap words */
"xchgb %b0,%h0" /* swap higher bytes */
:"=q" (x)
: "0" (x));
return x;
}
#define __constant_ntohl(x) \
((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
(((unsigned long int)(x) & 0x0000ff00U) << 8) | \
(((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
(((unsigned long int)(x) & 0xff000000U) >> 24)))
extern __inline__ unsigned short int
__ntohs(unsigned short int x)
{
__asm__("xchgb %b0,%h0" /* swap bytes */
: "=q" (x)
: "0" (x));
return x;
}
#define __constant_ntohs(x) \
((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
(((unsigned short int)(x) & 0xff00) >> 8))) \
#define __htonl(x) __ntohl(x)
#define __htons(x) __ntohs(x)
#define __constant_htonl(x) __constant_ntohl(x)
#define __constant_htons(x) __constant_ntohs(x)
#ifdef __OPTIMIZE__
# define ntohl(x) \
(__builtin_constant_p((long)(x)) ? \
__constant_ntohl((x)) : \
__ntohl((x)))
# define ntohs(x) \
(__builtin_constant_p((short)(x)) ? \
__constant_ntohs((x)) : \
__ntohs((x)))
# define htonl(x) \
(__builtin_constant_p((long)(x)) ? \
__constant_htonl((x)) : \
__htonl((x)))
# define htons(x) \
(__builtin_constant_p((short)(x)) ? \
__constant_htons((x)) : \
__htons((x)))
#endif
#endif

82
netboot/compile Normal file
View file

@ -0,0 +1,82 @@
#! /bin/sh
# Wrapper for compilers which do not understand `-c -o'.
# Copyright (C) 1999 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You 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.
# Usage:
# compile PROGRAM [ARGS]...
# `-o FOO.o' is removed from the args passed to the actual compile.
prog="$1"
shift
ofile=
cfile=
args=
while test $# -gt 0; do
case "$1" in
-o)
ofile="$2"
shift
;;
*.c)
cfile="$1"
args="$args $1"
;;
*)
args="$args $1"
;;
esac
shift
done
test -z "$ofile" && {
echo "compile: no \`-o' option seen" 1>&2
exit 1
}
test -z "$cfile" && {
echo "compile: no \`.c' file seen" 1>&2
exit 1
}
# Name of file we expect compiler to create.
cofile="`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'`"
# Create the lock directory.
lockdir="`echo $ofile | sed -e 's|/|_|g'`"
while true; do
if mkdir $lockdir > /dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir $lockdir; exit 1" 1 2 15
# Run the compile.
"$prog" $args
status=$?
if test -f "$cofile"; then
mv "$cofile" "$ofile"
fi
rmdir $lockdir
exit $status

225
netboot/config.c Normal file
View file

@ -0,0 +1,225 @@
#include "netboot.h"
#include "nic.h"
#include "config.h"
#undef INCLUDE_PCI
#if defined(INCLUDE_NEPCI) || defined(INCLUDE_EEPRO100) || defined (INCLUDE_3c59x)
/* || others later */
#if defined(NETBOOT32) /* only for 32 bit machines */
#define INCLUDE_PCI
/* #include <linux/pci.h> */
#include "pci.h"
static unsigned short pci_addrs[16];
struct pci_device pci_nic_list[] = {
#ifdef INCLUDE_NEPCI
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029,
"Realtek 8029"},
{ PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940,
"Winbond NE2000-PCI"}, /* "Winbond 89C940" */
{ PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000,
"Compex ReadyLink 2000"},
{ PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_ET32P2,
"KTI ET32P2"},
{PCI_VENDOR_ID_NETVIN, PCI_DEVICE_ID_NETVIN_NV5000SC,
"NetVin NV5000"},
{PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C926,
"VIA 82C926 Amazon"},
{PCI_VENDOR_ID_SURECOM, PCI_DEVICE_ID_SURECOM_NE34,
"SureCom NE34"},
#endif
#ifdef INCLUDE_EEPRO100
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
"Intel EtherExpressPro100"},
#endif
#ifdef INCLUDE_3c59x
{PCI_VENDOR_ID_VORTEX, PCI_DEVICE_ID_VORTEX_3c595, "3c595"},
#endif
/* other PCI NICs go here */
{0,}
};
#endif /* NETBOOT32 */
#endif /* INCLUDE_*PCI */
struct dispatch_table
{
char *nic_name;
struct nic *(*eth_probe)(struct nic *, unsigned short *);
unsigned short *probe_addrs; /* for probe overrides */
};
#ifdef INCLUDE_WD
extern struct nic *wd_probe(struct nic *, unsigned short *);
#endif
#ifdef INCLUDE_T503
extern struct nic *t503_probe(struct nic *, unsigned short *);
#endif
#if defined(INCLUDE_NE)
extern struct nic *ne_probe(struct nic *, unsigned short *);
#endif
#if defined(INCLUDE_NEPCI)
extern struct nic *nepci_probe(struct nic *, unsigned short *);
#endif
#ifdef INCLUDE_T509
extern struct nic *t509_probe(struct nic *, unsigned short *);
#endif
#ifdef INCLUDE_EEPRO100
extern struct nic *eepro100_probe(struct nic *, unsigned short *);
#endif
#ifdef INCLUDE_CS
extern struct nic *cs89x0_probe(struct nic *, unsigned short *);
#endif
#ifdef INCLUDE_NE2100
extern struct nic *ne2100_probe(struct nic *, unsigned short *);
#endif
#ifdef INCLUDE_3c59x
extern struct nic *VX_probe(struct nic *, unsigned short *);
#endif
/*
* NIC probing is in order of appearance in this table.
* If for some reason you want to change the order,
* just rearrange the entries (bracketed by the #ifdef/#endif)
*/
static struct dispatch_table NIC[] =
{
#ifdef INCLUDE_WD
{ "WD", wd_probe, 0 },
#endif
#ifdef INCLUDE_T503
{ "3C503", t503_probe, 0 },
#endif
#ifdef INCLUDE_NE
{ "NE*000", ne_probe, 0 },
#endif
#ifdef INCLUDE_T509
{ "3C5x9", t509_probe, 0 },
#endif
#ifdef INCLUDE_EEPRO100
{ "EEPRO100", eepro100_probe, 0 },
#endif
#ifdef INCLUDE_CS
{ "CS89x0", cs89x0_probe, 0 },
#endif
#ifdef INCLUDE_NE2100
{ "NE2100", ne2100_probe, 0 },
#endif
#ifdef INCLUDE_NEPCI
{ "NE*000/PCI", nepci_probe, pci_addrs },
#endif
#ifdef INCLUDE_3c59x
{"VorTex/PCI", VX_probe, pci_addrs},
#endif
/* this entry must always be last to mark the end of list */
{ 0, 0, 0 }
};
#define NIC_TABLE_SIZE (sizeof(NIC)/sizeof(NIC[0]))
static int eth_dummy(struct nic *nic)
{
return (0);
}
char packet[ETH_MAX_PACKET];
struct nic nic =
{
#ifdef NETBOOT32
(void (*)(struct nic *))eth_dummy, /* reset */
eth_dummy, /* poll */
(void (*)(struct nic *, char *,
unsigned int, unsigned int,
char *))eth_dummy, /* transmit */
(void (*)(struct nic *))eth_dummy, /* disable */
#endif
/* bcc has problems with complicated casts */
#ifdef NETBOOT16
eth_dummy,
eth_dummy,
eth_dummy,
eth_dummy,
#endif
1, /* aui */
arptable[ARP_CLIENT].node, /* node_addr */
packet, /* packet */
0, /* packetlen */
0 /* priv_data */
};
#if 0
void print_config(void)
{
struct dispatch_table *t;
#ifdef NETBOOT32
printf("Etherboot/32 version " VERSION
#ifdef NFS_BOOT
" ESC for menu"
#endif
" for ");
#endif
#ifdef NETBOOT16
/* you need to edit the version manually because bcc doesn't
do string literal concatenation yet */
printf("Etherboot/16 version 3.2 for ");
#endif
for (t = NIC; t->nic_name != 0; ++t)
printf("[%s]", t->nic_name);
printf("\r\n");
}
#endif
void eth_reset(void)
{
(*nic.reset)(&nic);
}
int eth_probe(void)
{
struct dispatch_table *t;
#ifdef INCLUDE_PCI
pci_addrs[0] = 0;
eth_pci_init(pci_nic_list, pci_addrs);
pci_addrs[1] = 0;
#endif
printf("Probing...");
for (t = NIC; t->nic_name != 0; ++t)
{
printf("[%s]", t->nic_name);
if ((*t->eth_probe)(&nic, t->probe_addrs))
return (1);
}
return (0);
}
int eth_poll(void)
{
return ((*nic.poll)(&nic));
}
void eth_transmit(char *d, unsigned int t, unsigned int s, char *p)
{
(*nic.transmit)(&nic, d, t, s, p);
twiddle();
}
void eth_disable(void)
{
(*nic.disable)(&nic);
}

8
netboot/config.h Normal file
View file

@ -0,0 +1,8 @@
extern struct nic nic;
extern void print_config(void);
extern void eth_reset(void);
extern int eth_probe(void);
extern int eth_poll(void);
extern void eth_transmit(char *d, unsigned int t, unsigned int s, char *p);
extern void eth_disable(void);

699
netboot/cs89x0.c Normal file
View file

@ -0,0 +1,699 @@
/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for etherboot. */
/*
This code is heavily based on the linux driver as written by
Russell Nelson <nelson@crynwr.com> and Donald Becker
<becker@cesdis.gsfc.nasa.gov> and modified by Mike Cruse
<mcruse@cti-ltd.com>. That driver has been released under the
conditions of the GNU Public License, thus this one is probably to
be considered "derived work". Therefore, there are some legal
obstacles in combining this file with etherboot's code, which is
released under a BSD style license.
So, if you want to actually use this code, you should make sure that
you are aware of the legal implications. I release *my* work into
the PUBLIC DOMAIN which implies that you can use it either under a
BSD style license, or under the conditions of the GPL, or under any
other conditions that you like. N.B. this does not apply to the
parts that originate from other authors. So, you should probably
contact them first and verify if they agree with your intended use.
If you contacted all of the above authors and they agreed to give
special permission for using this code under the conditions of a BSD
style license, then please do let me know.
ChangeLog:
Thu Dec 6 22:40:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
* disabled all "advanced" features; this should make the code more reliable
* reorganized the reset function
* always reset the address port, so that autoprobing will continue working
* some cosmetic changes
* 2.5
Thu Dec 5 21:00:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
* tested the code against a CS8900 card
* lots of minor bug fixes and adjustments
* this is the first release, that actually works! it still requires some
changes in order to be more tolerant to different environments
* 4
Fri Nov 22 23:00:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
* read the manuals for the CS89x0 chipsets and took note of all the
changes that will be neccessary in order to adapt Russel Nelson's code
to the requirements of a BOOT-Prom
* 6
Thu Nov 19 22:00:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
* Synched with Russel Nelson's current code (v1.00)
* 2
Thu Nov 12 18:00:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
* Cleaned up some of the code and tried to optimize the code size.
* 1.5
Sun Nov 10 16:30:00 1996 Markus Gutschke <gutschk@math.uni-muenster.de>
* First experimental release. This code compiles fine, but I
have no way of testing whether it actually works.
* I did not (yet) bother to make the code 16bit aware, so for
the time being, it will only work for netboot-32.
* 12
*/
#ifdef INCLUDE_CS
#include "netboot.h"
#include "nic.h"
#include "cs89x0.h"
static unsigned short eth_nic_base;
static unsigned long eth_mem_start;
static unsigned short eth_irq;
static unsigned short eth_cs_type; /* one of: CS8900, CS8920, CS8920M */
static unsigned short eth_auto_neg_cnf;
static unsigned short eth_adapter_cnf;
static unsigned short eth_linectl;
static unsigned char eth_vendor;
/*************************************************************************
CS89x0 - specific routines
**************************************************************************/
static int inline readreg(portno)
int portno;
{
outw(eth_nic_base + ADD_PORT, portno);
return inw(eth_nic_base + DATA_PORT);
}
static void inline writereg(portno,value)
int portno;
int value;
{
outw(eth_nic_base + ADD_PORT, portno);
outw(eth_nic_base + DATA_PORT, value);
return;
}
/*************************************************************************
EEPROM access
**************************************************************************/
static int wait_eeprom_ready()
{
long tmo = currticks() + 4*18L;
/* check to see if the EEPROM is ready, a timeout is used -
just in case EEPROM is ready when SI_BUSY in the
PP_SelfST is clear */
while(readreg(PP_SelfST) & SI_BUSY) {
if (currticks() - tmo >= 0)
return -1; }
return 0;
}
static int get_eeprom_data(off,len,buffer)
int off;
int len;
unsigned short *buffer;
{
int i;
#if defined(EDEBUG)
printf("\r\ncs: EEPROM data from %x for %x:",off,len);
#endif
for (i = 0; i < len; i++) {
if (wait_eeprom_ready() < 0)
return -1;
/* Now send the EEPROM read command and EEPROM location
to read */
writereg(PP_EECMD, (off + i) | EEPROM_READ_CMD);
if (wait_eeprom_ready() < 0)
return -1;
buffer[i] = readreg(PP_EEData);
#if defined(EDEBUG)
if (!(i%10))
printf("\r\ncs: ");
printf("%x ", buffer[i]);
#endif
}
#if defined(EDEBUG)
printf("\r\n");
#endif
return(0);
}
static int get_eeprom_chksum(off, len, buffer)
int off;
int len;
unsigned short *buffer;
{
int i, cksum;
cksum = 0;
for (i = 0; i < len; i++)
cksum += buffer[i];
cksum &= 0xffff;
if (cksum == 0)
return 0;
return -1;
}
/*************************************************************************
Activate all of the available media and probe for network
**************************************************************************/
static void clrline()
{
int i;
putchar('\r');
for (i = 79; i--; ) putchar(' ');
printf("\rcs: ");
return;
}
static void control_dc_dc(on_not_off)
int on_not_off;
{
unsigned int selfcontrol;
long tmo = currticks() + 18;
/* control the DC to DC convertor in the SelfControl register. */
selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
if (((eth_adapter_cnf & A_CNF_DC_DC_POLARITY) != 0) ^ on_not_off)
selfcontrol |= HCB1;
else
selfcontrol &= ~HCB1;
writereg(PP_SelfCTL, selfcontrol);
/* Wait for the DC/DC converter to power up - 1000ms */
while (currticks() - tmo < 0);
return;
}
static int detect_tp()
{
long tmo;
/* Turn on the chip auto detection of 10BT/ AUI */
clrline(); printf("attempting %s:","TP");
/* If connected to another full duplex capable 10-Base-T card
the link pulses seem to be lost when the auto detect bit in
the LineCTL is set. To overcome this the auto detect bit
will be cleared whilst testing the 10-Base-T interface.
This would not be necessary for the sparrow chip but is
simpler to do it anyway. */
writereg(PP_LineCTL, eth_linectl &~ AUI_ONLY);
control_dc_dc(0);
/* Delay for the hardware to work out if the TP cable is
present - 150ms */
for (tmo = currticks() + 4; currticks() - tmo < 0; );
if ((readreg(PP_LineST) & LINK_OK) == 0)
return 0;
if (eth_cs_type != CS8900) {
writereg(PP_AutoNegCTL, eth_auto_neg_cnf & AUTO_NEG_MASK);
if ((eth_auto_neg_cnf & AUTO_NEG_BITS) == AUTO_NEG_ENABLE) {
printf(" negotiating duplex... ");
while (readreg(PP_AutoNegST) & AUTO_NEG_BUSY) {
if (currticks() - tmo > 40*18) {
printf("time out ");
break;
}
}
}
if (readreg(PP_AutoNegST) & FDX_ACTIVE)
printf("using full duplex");
else
printf("using half duplex");
}
return A_CNF_MEDIA_10B_T;
}
/* send a test packet - return true if carrier bits are ok */
static int send_test_pkt(struct nic *nic)
{
static char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
0, 46, /*A 46 in network order */
0, 0, /*DSAP=0 & SSAP=0 fields */
0xf3,0 /*Control (Test Req+P bit set)*/ };
long tmo;
writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON);
bcopy(nic->node_addr,testpacket,ETHER_ADDR_SIZE);
bcopy(nic->node_addr,testpacket+ETHER_ADDR_SIZE,
ETHER_ADDR_SIZE);
outw(eth_nic_base + TX_CMD_PORT, TX_AFTER_ALL);
outw(eth_nic_base + TX_LEN_PORT, ETH_MIN_PACKET);
/* Test to see if the chip has allocated memory for the packet */
for (tmo = currticks() + 2;
(readreg(PP_BusST) & READY_FOR_TX_NOW) == 0; )
if (currticks() - tmo >= 0)
return(0);
/* Write the contents of the packet */
outsw(eth_nic_base + TX_FRAME_PORT, testpacket,
(ETH_MIN_PACKET+1)>>1);
printf(" sending test packet ");
/* wait a couple of timer ticks for packet to be received */
for (tmo = currticks() + 2; currticks() - tmo < 0; );
if ((readreg(PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
printf("succeeded");
return 1;
}
printf("failed");
return 0;
}
static int detect_aui(struct nic *nic)
{
clrline(); printf("attempting %s:","AUI");
control_dc_dc(0);
writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
if (send_test_pkt(nic)) {
return A_CNF_MEDIA_AUI; }
else
return 0;
}
static int detect_bnc(struct nic *nic)
{
clrline(); printf("attempting %s:","BNC");
control_dc_dc(1);
writereg(PP_LineCTL, (eth_linectl & ~AUTO_AUI_10BASET) | AUI_ONLY);
if (send_test_pkt(nic)) {
return A_CNF_MEDIA_10B_2; }
else
return 0;
}
/**************************************************************************
ETH_RESET - Reset adapter
***************************************************************************/
void cs89x0_reset(struct nic *nic)
{
int i;
long reset_tmo;
if(eth_vendor!=VENDOR_CS89x0)
return;
writereg(PP_SelfCTL, readreg(PP_SelfCTL) | POWER_ON_RESET);
/* wait for two ticks; that is 2*55ms */
for (reset_tmo = currticks() + 2;
reset_tmo > currticks(); );
if (eth_cs_type != CS8900) {
/* Hardware problem requires PNP registers to be reconfigured
after a reset */
if (eth_irq != 0xFFFF) {
outw(eth_nic_base + ADD_PORT, PP_CS8920_ISAINT);
outb(eth_nic_base + DATA_PORT, eth_irq);
outb(eth_nic_base + DATA_PORT + 1, 0); }
if (eth_mem_start) {
outw(eth_nic_base + ADD_PORT, PP_CS8920_ISAMemB);
outb(eth_nic_base + DATA_PORT, (eth_mem_start >> 8) & 0xff);
outb(eth_nic_base + DATA_PORT + 1, (eth_mem_start >> 24) & 0xff); } }
/* Wait until the chip is reset */
for (reset_tmo = currticks() + 2;
(readreg(PP_SelfST) & INIT_DONE) == 0 &&
currticks() - reset_tmo < 0; );
/* disable interrupts and memory accesses */
writereg(PP_BusCTL, 0);
/* set the ethernet address */
for (i=0; i < ETHER_ADDR_SIZE/2; i++)
writereg(PP_IA+i*2,
nic->node_addr[i*2] |
(nic->node_addr[i*2+1] << 8));
/* receive only error free packets addressed to this card */
writereg(PP_RxCTL, DEF_RX_ACCEPT);
/* do not generate any interrupts on receive operations */
writereg(PP_RxCFG, 0);
/* do not generate any interrupts on transmit operations */
writereg(PP_TxCFG, 0);
/* do not generate any interrupts on buffer operations */
writereg(PP_BufCFG, 0);
/* reset address port, so that autoprobing will keep working */
outw(eth_nic_base + ADD_PORT, PP_ChipID);
return;
}
/**************************************************************************
ETH_TRANSMIT - Transmit a frame
***************************************************************************/
static void cs89x0_transmit(
struct nic *nic,
char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
{
long tmo;
int sr;
if(eth_vendor!=VENDOR_CS89x0)
return;
/* does this size have to be rounded??? please,
somebody have a look in the specs */
if ((sr = ((s + ETHER_HDR_SIZE + 1)&~1)) < ETH_MIN_PACKET)
sr = ETH_MIN_PACKET;
retry:
/* initiate a transmit sequence */
outw(eth_nic_base + TX_CMD_PORT, TX_AFTER_ALL);
outw(eth_nic_base + TX_LEN_PORT, sr);
/* Test to see if the chip has allocated memory for the packet */
if ((readreg(PP_BusST) & READY_FOR_TX_NOW) == 0) {
/* Oops... this should not happen! */
printf("cs: unable to send packet; retrying...\r\n");
for (tmo = currticks() + 5*18; currticks() - tmo < 0; );
cs89x0_reset(nic);
goto retry; }
/* Write the contents of the packet */
outsw(eth_nic_base + TX_FRAME_PORT, d, ETHER_ADDR_SIZE/2);
outsw(eth_nic_base + TX_FRAME_PORT, nic->node_addr,
ETHER_ADDR_SIZE/2);
outw(eth_nic_base + TX_FRAME_PORT, ((t >> 8)&0xFF)|(t << 8));
outsw(eth_nic_base + TX_FRAME_PORT, p, (s+1)/2);
for (sr = sr/2 - (s+1)/2 - ETHER_ADDR_SIZE - 1; sr-- > 0;
outw(eth_nic_base + TX_FRAME_PORT, 0));
/* wait for transfer to succeed */
for (tmo = currticks()+5*18;
(s = readreg(PP_TxEvent)&~0x1F) == 0 && currticks() - tmo < 0;
twiddle());
if ((s & TX_SEND_OK_BITS) != TX_OK) {
printf("\r\ntransmission error 0x%x\r\n", s);
}
return;
}
/**************************************************************************
ETH_POLL - Wait for a frame
***************************************************************************/
static int cs89x0_poll(struct nic *nic)
{
int status;
if(eth_vendor!=VENDOR_CS89x0)
return 0;
status = readreg(PP_RxEvent);
if ((status & RX_OK) == 0)
return(0);
status = inw(eth_nic_base + RX_FRAME_PORT);
nic->packetlen = inw(eth_nic_base + RX_FRAME_PORT);
insw(eth_nic_base + RX_FRAME_PORT, nic->packet, nic->packetlen >> 1);
if (nic->packetlen & 1)
nic->packet[nic->packetlen-1] = inw(eth_nic_base + RX_FRAME_PORT);
return 1;
}
static void cs89x0_disable(struct nic *nic)
{
}
/**************************************************************************
ETH_PROBE - Look for an adapter
***************************************************************************/
struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
{
static const unsigned int netcard_portlist[] = {
#ifdef CS_SCAN
CS_SCAN,
#else /* use "conservative" default values for autoprobing */
0x300,0x320,0x340,0x200,0x220,0x240,
0x260,0x280,0x2a0,0x2c0,0x2e0,
/* if that did not work, then be more aggressive */
0x301,0x321,0x341,0x201,0x221,0x241,
0x261,0x281,0x2a1,0x2c1,0x2e1,
#endif
0};
int i, result = -1;
unsigned rev_type = 0, ioaddr, ioidx, isa_cnf, cs_revision;
unsigned short eeprom_buff[CHKSUM_LEN];
for (eth_vendor = VENDOR_NONE, ioidx = 0;
eth_vendor == VENDOR_NONE &&
(ioaddr=netcard_portlist[ioidx++]) != 0;) {
/* if they give us an odd I/O address, then do ONE write to
the address port, to get it back to address zero, where we
expect to find the EISA signature word. */
if (ioaddr & 1) {
ioaddr &= ~1;
if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG)
continue;
outw(ioaddr + ADD_PORT, PP_ChipID);
}
if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG)
continue;
eth_nic_base = ioaddr;
/* get the chip type */
rev_type = readreg(PRODUCT_ID_ADD);
eth_cs_type = rev_type &~ REVISON_BITS;
cs_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
printf("\r\ncs: cs89%c0%s rev %c, base 0x%x",
eth_cs_type==CS8900?'0':'2',
eth_cs_type==CS8920M?"M":"",
cs_revision,
eth_nic_base);
/* First check to see if an EEPROM is attached*/
if ((readreg(PP_SelfST) & EEPROM_PRESENT) == 0) {
printf("\r\ncs: no EEPROM...\r\n");
outw(eth_nic_base + ADD_PORT, PP_ChipID);
continue; }
else if (get_eeprom_data(START_EEPROM_DATA,CHKSUM_LEN,
eeprom_buff) < 0) {
printf("\r\ncs: EEPROM read failed...\r\n");
outw(eth_nic_base + ADD_PORT, PP_ChipID);
continue; }
else if (get_eeprom_chksum(START_EEPROM_DATA,CHKSUM_LEN,
eeprom_buff) < 0) {
printf("\r\ncs: EEPROM checksum bad...\r\n");
outw(eth_nic_base + ADD_PORT, PP_ChipID);
continue; }
/* get transmission control word but keep the
autonegotiation bits */
eth_auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
/* Store adapter configuration */
eth_adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET/2];
/* Store ISA configuration */
isa_cnf = eeprom_buff[ISA_CNF_OFFSET/2];
/* store the initial memory base address */
eth_mem_start = eeprom_buff[PACKET_PAGE_OFFSET/2] << 8;
printf("%s%s%s, addr ",
(eth_adapter_cnf & A_CNF_10B_T)?", RJ-45":"",
(eth_adapter_cnf & A_CNF_AUI)?", AUI":"",
(eth_adapter_cnf & A_CNF_10B_2)?", BNC":"");
/* If this is a CS8900 then no pnp soft */
if (eth_cs_type != CS8900 &&
/* Check if the ISA IRQ has been set */
(i = readreg(PP_CS8920_ISAINT) & 0xff,
(i != 0 && i < CS8920_NO_INTS)))
eth_irq = i;
else {
i = isa_cnf & INT_NO_MASK;
if (eth_cs_type == CS8900) {
/* the table that follows is dependent
upon how you wired up your cs8900
in your system. The table is the
same as the cs8900 engineering demo
board. irq_map also depends on the
contents of the table. Also see
write_irq, which is the reverse
mapping of the table below. */
if (i < 4) i = "\012\013\014\005"[i];
else printf("\r\ncs: BUG: isa_config is %d\r\n", i); }
eth_irq = i; }
/* Retrieve and print the ethernet address. */
for (i=0; i<ETHER_ADDR_SIZE; i++) {
printf("%b%s",(int)(nic->node_addr[i] =
((unsigned char *)eeprom_buff)[i]),
i < ETHER_ADDR_SIZE-1 ? ":" : "\r\n"); }
/* Set the LineCTL quintuplet based on adapter
configuration read from EEPROM */
if ((eth_adapter_cnf & A_CNF_EXTND_10B_2) &&
(eth_adapter_cnf & A_CNF_LOW_RX_SQUELCH))
eth_linectl = LOW_RX_SQUELCH;
else
eth_linectl = 0;
/* check to make sure that they have the "right"
hardware available */
switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
case A_CNF_MEDIA_10B_T: result = eth_adapter_cnf & A_CNF_10B_T;
break;
case A_CNF_MEDIA_AUI: result = eth_adapter_cnf & A_CNF_AUI;
break;
case A_CNF_MEDIA_10B_2: result = eth_adapter_cnf & A_CNF_10B_2;
break;
default: result = eth_adapter_cnf & (A_CNF_10B_T | A_CNF_AUI |
A_CNF_10B_2);
}
if (!result) {
printf("cs: EEPROM is configured for unavailable media\r\n");
error:
writereg(PP_LineCTL, readreg(PP_LineCTL) &
~(SERIAL_TX_ON | SERIAL_RX_ON));
outw(eth_nic_base + ADD_PORT, PP_ChipID);
continue;
}
/* Initialize the card for probing of the attached media */
eth_vendor = VENDOR_CS89x0;
cs89x0_reset(nic);
eth_vendor = VENDOR_NONE;
/* set the hardware to the configured choice */
switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
case A_CNF_MEDIA_10B_T:
result = detect_tp();
if (!result) {
clrline();
printf("10Base-T (RJ-45%s",
") has no cable\r\n"); }
/* check "ignore missing media" bit */
if (eth_auto_neg_cnf & IMM_BIT)
/* Yes! I don't care if I see a link pulse */
result = A_CNF_MEDIA_10B_T;
break;
case A_CNF_MEDIA_AUI:
result = detect_aui(nic);
if (!result) {
clrline();
printf("10Base-5 (AUI%s",
") has no cable\r\n"); }
/* check "ignore missing media" bit */
if (eth_auto_neg_cnf & IMM_BIT)
/* Yes! I don't care if I see a carrrier */
result = A_CNF_MEDIA_AUI;
break;
case A_CNF_MEDIA_10B_2:
result = detect_bnc(nic);
if (!result) {
clrline();
printf("10Base-2 (BNC%s",
") has no cable\r\n"); }
/* check "ignore missing media" bit */
if (eth_auto_neg_cnf & IMM_BIT)
/* Yes! I don't care if I can xmit a packet */
result = A_CNF_MEDIA_10B_2;
break;
case A_CNF_MEDIA_AUTO:
writereg(PP_LineCTL, eth_linectl | AUTO_AUI_10BASET);
if (eth_adapter_cnf & A_CNF_10B_T)
if ((result = detect_tp()) != 0)
break;
if (eth_adapter_cnf & A_CNF_AUI)
if ((result = detect_aui(nic)) != 0)
break;
if (eth_adapter_cnf & A_CNF_10B_2)
if ((result = detect_bnc(nic)) != 0)
break;
clrline(); printf("no media detected\r\n");
goto error;
}
clrline();
switch(result) {
case 0: printf("no network cable attached to configured media\r\n");
goto error;
case A_CNF_MEDIA_10B_T: printf("using 10Base-T (RJ-45)\r\n");
break;
case A_CNF_MEDIA_AUI: printf("using 10Base-5 (AUI)\r\n");
break;
case A_CNF_MEDIA_10B_2: printf("using 10Base-2 (BNC)\r\n");
break;
}
/* Turn on both receive and transmit operations */
writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_RX_ON |
SERIAL_TX_ON);
eth_vendor = VENDOR_CS89x0;
}
nic->reset = cs89x0_reset;
nic->poll = cs89x0_poll;
nic->transmit = cs89x0_transmit;
nic->disable = cs89x0_disable;
return nic;
}
#endif /* INCLUDE_CS */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

465
netboot/cs89x0.h Normal file
View file

@ -0,0 +1,465 @@
/* This file has been copied from Russel Nelson's device driver for
Linux. Please look into the header of cs89x0.c for details on the
legal implications! */
/* Copyright, 1988-1992, Russell Nelson, Crynwr Software
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 1.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */
/* offset 2h -> Model/Product Number */
/* offset 3h -> Chip Revision Number */
#define PP_ISAIOB 0x0020 /* IO base address */
#define PP_CS8900_ISAINT 0x0022 /* ISA interrupt select */
#define PP_CS8920_ISAINT 0x0370 /* ISA interrupt select */
#define PP_CS8900_ISADMA 0x0024 /* ISA Rec DMA channel */
#define PP_CS8920_ISADMA 0x0374 /* ISA Rec DMA channel */
#define PP_ISASOF 0x0026 /* ISA DMA offset */
#define PP_DmaFrameCnt 0x0028 /* ISA DMA Frame count */
#define PP_DmaByteCnt 0x002A /* ISA DMA Byte count */
#define PP_CS8900_ISAMemB 0x002C /* Memory base */
#define PP_CS8920_ISAMemB 0x0348 /* */
#define PP_ISABootBase 0x0030 /* Boot Prom base */
#define PP_ISABootMask 0x0034 /* Boot Prom Mask */
/* EEPROM data and command registers */
#define PP_EECMD 0x0040 /* NVR Interface Command register */
#define PP_EEData 0x0042 /* NVR Interface Data Register */
#define PP_DebugReg 0x0044 /* Debug Register */
#define PP_RxCFG 0x0102 /* Rx Bus config */
#define PP_RxCTL 0x0104 /* Receive Control Register */
#define PP_TxCFG 0x0106 /* Transmit Config Register */
#define PP_TxCMD 0x0108 /* Transmit Command Register */
#define PP_BufCFG 0x010A /* Bus configuration Register */
#define PP_LineCTL 0x0112 /* Line Config Register */
#define PP_SelfCTL 0x0114 /* Self Command Register */
#define PP_BusCTL 0x0116 /* ISA bus control Register */
#define PP_TestCTL 0x0118 /* Test Register */
#define PP_AutoNegCTL 0x011C /* Auto Negotiation Ctrl */
#define PP_ISQ 0x0120 /* Interrupt Status */
#define PP_RxEvent 0x0124 /* Rx Event Register */
#define PP_TxEvent 0x0128 /* Tx Event Register */
#define PP_BufEvent 0x012C /* Bus Event Register */
#define PP_RxMiss 0x0130 /* Receive Miss Count */
#define PP_TxCol 0x0132 /* Transmit Collision Count */
#define PP_LineST 0x0134 /* Line State Register */
#define PP_SelfST 0x0136 /* Self State register */
#define PP_BusST 0x0138 /* Bus Status */
#define PP_TDR 0x013C /* Time Domain Reflectometry */
#define PP_AutoNegST 0x013E /* Auto Neg Status */
#define PP_TxCommand 0x0144 /* Tx Command */
#define PP_TxLength 0x0146 /* Tx Length */
#define PP_LAF 0x0150 /* Hash Table */
#define PP_IA 0x0158 /* Physical Address Register */
#define PP_RxStatus 0x0400 /* Receive start of frame */
#define PP_RxLength 0x0402 /* Receive Length of frame */
#define PP_RxFrame 0x0404 /* Receive frame pointer */
#define PP_TxFrame 0x0A00 /* Transmit frame pointer */
/* Primary I/O Base Address. If no I/O base is supplied by the user, then this */
/* can be used as the default I/O base to access the PacketPage Area. */
#define DEFAULTIOBASE 0x0300
#define FIRST_IO 0x020C /* First I/O port to check */
#define LAST_IO 0x037C /* Last I/O port to check (+10h) */
#define ADD_MASK 0x3000 /* Mask it use of the ADD_PORT register */
#define ADD_SIG 0x3000 /* Expected ID signature */
#define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */
#ifdef IBMEIPKT
#define EISA_ID_SIG 0x4D24 /* IBM */
#define PART_NO_SIG 0x1010 /* IBM */
#define MONGOOSE_BIT 0x0000 /* IBM */
#else
#define EISA_ID_SIG 0x630E /* PnP Vendor ID (same as chip id for Crystal board) */
#define PART_NO_SIG 0x4000 /* ID code CS8920 board (PnP Vendor Product code) */
#define MONGOOSE_BIT 0x2000 /* PART_NO_SIG + MONGOOSE_BUT => ID of mongoose */
#endif
#define PRODUCT_ID_ADD 0x0002 /* Address of product ID */
/* Mask to find out the types of registers */
#define REG_TYPE_MASK 0x001F
/* Eeprom Commands */
#define ERSE_WR_ENBL 0x00F0
#define ERSE_WR_DISABLE 0x0000
/* Defines Control/Config register quintuplet numbers */
#define RX_BUF_CFG 0x0003
#define RX_CONTROL 0x0005
#define TX_CFG 0x0007
#define TX_COMMAND 0x0009
#define BUF_CFG 0x000B
#define LINE_CONTROL 0x0013
#define SELF_CONTROL 0x0015
#define BUS_CONTROL 0x0017
#define TEST_CONTROL 0x0019
/* Defines Status/Count registers quintuplet numbers */
#define RX_EVENT 0x0004
#define TX_EVENT 0x0008
#define BUF_EVENT 0x000C
#define RX_MISS_COUNT 0x0010
#define TX_COL_COUNT 0x0012
#define LINE_STATUS 0x0014
#define SELF_STATUS 0x0016
#define BUS_STATUS 0x0018
#define TDR 0x001C
/* PP_RxCFG - Receive Configuration and Interrupt Mask bit definition - Read/write */
#define SKIP_1 0x0040
#define RX_STREAM_ENBL 0x0080
#define RX_OK_ENBL 0x0100
#define RX_DMA_ONLY 0x0200
#define AUTO_RX_DMA 0x0400
#define BUFFER_CRC 0x0800
#define RX_CRC_ERROR_ENBL 0x1000
#define RX_RUNT_ENBL 0x2000
#define RX_EXTRA_DATA_ENBL 0x4000
/* PP_RxCTL - Receive Control bit definition - Read/write */
#define RX_IA_HASH_ACCEPT 0x0040
#define RX_PROM_ACCEPT 0x0080
#define RX_OK_ACCEPT 0x0100
#define RX_MULTCAST_ACCEPT 0x0200
#define RX_IA_ACCEPT 0x0400
#define RX_BROADCAST_ACCEPT 0x0800
#define RX_BAD_CRC_ACCEPT 0x1000
#define RX_RUNT_ACCEPT 0x2000
#define RX_EXTRA_DATA_ACCEPT 0x4000
#define RX_ALL_ACCEPT (RX_PROM_ACCEPT|RX_BAD_CRC_ACCEPT|RX_RUNT_ACCEPT|RX_EXTRA_DATA_ACCEPT)
/* Default receive mode - individually addressed, broadcast, and error free */
#define DEF_RX_ACCEPT (RX_IA_ACCEPT | RX_BROADCAST_ACCEPT | RX_OK_ACCEPT)
/* PP_TxCFG - Transmit Configuration Interrupt Mask bit definition - Read/write */
#define TX_LOST_CRS_ENBL 0x0040
#define TX_SQE_ERROR_ENBL 0x0080
#define TX_OK_ENBL 0x0100
#define TX_LATE_COL_ENBL 0x0200
#define TX_JBR_ENBL 0x0400
#define TX_ANY_COL_ENBL 0x0800
#define TX_16_COL_ENBL 0x8000
/* PP_TxCMD - Transmit Command bit definition - Read-only */
#define TX_START_4_BYTES 0x0000
#define TX_START_64_BYTES 0x0040
#define TX_START_128_BYTES 0x0080
#define TX_START_ALL_BYTES 0x00C0
#define TX_FORCE 0x0100
#define TX_ONE_COL 0x0200
#define TX_TWO_PART_DEFF_DISABLE 0x0400
#define TX_NO_CRC 0x1000
#define TX_RUNT 0x2000
/* PP_BufCFG - Buffer Configuration Interrupt Mask bit definition - Read/write */
#define GENERATE_SW_INTERRUPT 0x0040
#define RX_DMA_ENBL 0x0080
#define READY_FOR_TX_ENBL 0x0100
#define TX_UNDERRUN_ENBL 0x0200
#define RX_MISS_ENBL 0x0400
#define RX_128_BYTE_ENBL 0x0800
#define TX_COL_COUNT_OVRFLOW_ENBL 0x1000
#define RX_MISS_COUNT_OVRFLOW_ENBL 0x2000
#define RX_DEST_MATCH_ENBL 0x8000
/* PP_LineCTL - Line Control bit definition - Read/write */
#define SERIAL_RX_ON 0x0040
#define SERIAL_TX_ON 0x0080
#define AUI_ONLY 0x0100
#define AUTO_AUI_10BASET 0x0200
#define MODIFIED_BACKOFF 0x0800
#define NO_AUTO_POLARITY 0x1000
#define TWO_PART_DEFDIS 0x2000
#define LOW_RX_SQUELCH 0x4000
/* PP_SelfCTL - Software Self Control bit definition - Read/write */
#define POWER_ON_RESET 0x0040
#define SW_STOP 0x0100
#define SLEEP_ON 0x0200
#define AUTO_WAKEUP 0x0400
#define HCB0_ENBL 0x1000
#define HCB1_ENBL 0x2000
#define HCB0 0x4000
#define HCB1 0x8000
/* PP_BusCTL - ISA Bus Control bit definition - Read/write */
#define RESET_RX_DMA 0x0040
#define MEMORY_ON 0x0400
#define DMA_BURST_MODE 0x0800
#define IO_CHANNEL_READY_ON 0x1000
#define RX_DMA_SIZE_64K 0x2000
#define ENABLE_IRQ 0x8000
/* PP_TestCTL - Test Control bit definition - Read/write */
#define LINK_OFF 0x0080
#define ENDEC_LOOPBACK 0x0200
#define AUI_LOOPBACK 0x0400
#define BACKOFF_OFF 0x0800
#define FAST_TEST 0x8000
/* PP_RxEvent - Receive Event Bit definition - Read-only */
#define RX_IA_HASHED 0x0040
#define RX_DRIBBLE 0x0080
#define RX_OK 0x0100
#define RX_HASHED 0x0200
#define RX_IA 0x0400
#define RX_BROADCAST 0x0800
#define RX_CRC_ERROR 0x1000
#define RX_RUNT 0x2000
#define RX_EXTRA_DATA 0x4000
#define HASH_INDEX_MASK 0x0FC00
/* PP_TxEvent - Transmit Event Bit definition - Read-only */
#define TX_LOST_CRS 0x0040
#define TX_SQE_ERROR 0x0080
#define TX_OK 0x0100
#define TX_LATE_COL 0x0200
#define TX_JBR 0x0400
#define TX_16_COL 0x8000
#define TX_SEND_OK_BITS (TX_OK|TX_LOST_CRS)
#define TX_COL_COUNT_MASK 0x7800
/* PP_BufEvent - Buffer Event Bit definition - Read-only */
#define SW_INTERRUPT 0x0040
#define RX_DMA 0x0080
#define READY_FOR_TX 0x0100
#define TX_UNDERRUN 0x0200
#define RX_MISS 0x0400
#define RX_128_BYTE 0x0800
#define TX_COL_OVRFLW 0x1000
#define RX_MISS_OVRFLW 0x2000
#define RX_DEST_MATCH 0x8000
/* PP_LineST - Ethernet Line Status bit definition - Read-only */
#define LINK_OK 0x0080
#define AUI_ON 0x0100
#define TENBASET_ON 0x0200
#define POLARITY_OK 0x1000
#define CRS_OK 0x4000
/* PP_SelfST - Chip Software Status bit definition */
#define ACTIVE_33V 0x0040
#define INIT_DONE 0x0080
#define SI_BUSY 0x0100
#define EEPROM_PRESENT 0x0200
#define EEPROM_OK 0x0400
#define EL_PRESENT 0x0800
#define EE_SIZE_64 0x1000
/* PP_BusST - ISA Bus Status bit definition */
#define TX_BID_ERROR 0x0080
#define READY_FOR_TX_NOW 0x0100
/* PP_AutoNegCTL - Auto Negotiation Control bit definition */
#define RE_NEG_NOW 0x0040
#define ALLOW_FDX 0x0080
#define AUTO_NEG_ENABLE 0x0100
#define NLP_ENABLE 0x0200
#define FORCE_FDX 0x8000
#define AUTO_NEG_BITS (FORCE_FDX|NLP_ENABLE|AUTO_NEG_ENABLE)
#define AUTO_NEG_MASK (FORCE_FDX|NLP_ENABLE|AUTO_NEG_ENABLE|ALLOW_FDX|RE_NEG_NOW)
/* PP_AutoNegST - Auto Negotiation Status bit definition */
#define AUTO_NEG_BUSY 0x0080
#define FLP_LINK 0x0100
#define FLP_LINK_GOOD 0x0800
#define LINK_FAULT 0x1000
#define HDX_ACTIVE 0x4000
#define FDX_ACTIVE 0x8000
/* The following block defines the ISQ event types */
#define ISQ_RECEIVER_EVENT 0x04
#define ISQ_TRANSMITTER_EVENT 0x08
#define ISQ_BUFFER_EVENT 0x0c
#define ISQ_RX_MISS_EVENT 0x10
#define ISQ_TX_COL_EVENT 0x12
#define ISQ_EVENT_MASK 0x003F /* ISQ mask to find out type of event */
#define ISQ_HIST 16 /* small history buffer */
#define AUTOINCREMENT 0x8000 /* Bit mask to set bit-15 for autoincrement */
#define TXRXBUFSIZE 0x0600
#define RXDMABUFSIZE 0x8000
#define RXDMASIZE 0x4000
#define TXRX_LENGTH_MASK 0x07FF
/* rx options bits */
#define RCV_WITH_RXON 1 /* Set SerRx ON */
#define RCV_COUNTS 2 /* Use Framecnt1 */
#define RCV_PONG 4 /* Pong respondent */
#define RCV_DONG 8 /* Dong operation */
#define RCV_POLLING 0x10 /* Poll RxEvent */
#define RCV_ISQ 0x20 /* Use ISQ, int */
#define RCV_AUTO_DMA 0x100 /* Set AutoRxDMAE */
#define RCV_DMA 0x200 /* Set RxDMA only */
#define RCV_DMA_ALL 0x400 /* Copy all DMA'ed */
#define RCV_FIXED_DATA 0x800 /* Every frame same */
#define RCV_IO 0x1000 /* Use ISA IO only */
#define RCV_MEMORY 0x2000 /* Use ISA Memory */
#define RAM_SIZE 0x1000 /* The card has 4k bytes or RAM */
#define PKT_START PP_TxFrame /* Start of packet RAM */
#define RX_FRAME_PORT 0x0000
#define TX_FRAME_PORT RX_FRAME_PORT
#define TX_CMD_PORT 0x0004
#define TX_NOW 0x0000 /* Tx packet after 5 bytes copied */
#define TX_AFTER_381 0x0020 /* Tx packet after 381 bytes copied */
#define TX_AFTER_ALL 0x0060 /* Tx packet after all bytes copied */
#define TX_LEN_PORT 0x0006
#define ISQ_PORT 0x0008
#define ADD_PORT 0x000A
#define DATA_PORT 0x000C
#define EEPROM_WRITE_EN 0x00F0
#define EEPROM_WRITE_DIS 0x0000
#define EEPROM_WRITE_CMD 0x0100
#define EEPROM_READ_CMD 0x0200
/* Receive Header */
/* Description of header of each packet in receive area of memory */
#define RBUF_EVENT_LOW 0 /* Low byte of RxEvent - status of received frame */
#define RBUF_EVENT_HIGH 1 /* High byte of RxEvent - status of received frame */
#define RBUF_LEN_LOW 2 /* Length of received data - low byte */
#define RBUF_LEN_HI 3 /* Length of received data - high byte */
#define RBUF_HEAD_LEN 4 /* Length of this header */
#define CHIP_READ 0x1 /* Used to mark state of the repins code (chip or dma) */
#define DMA_READ 0x2 /* Used to mark state of the repins code (chip or dma) */
/* for bios scan */
/* */
#ifdef CSDEBUG
/* use these values for debugging bios scan */
#define BIOS_START_SEG 0x00000
#define BIOS_OFFSET_INC 0x0010
#else
#define BIOS_START_SEG 0x0c000
#define BIOS_OFFSET_INC 0x0200
#endif
#define BIOS_LAST_OFFSET 0x0fc00
/* Byte offsets into the EEPROM configuration buffer */
#define ISA_CNF_OFFSET 0x6
#define TX_CTL_OFFSET (ISA_CNF_OFFSET + 8) /* 8900 eeprom */
#define AUTO_NEG_CNF_OFFSET (ISA_CNF_OFFSET + 8) /* 8920 eeprom */
/* the assumption here is that the bits in the eeprom are generally */
/* in the same position as those in the autonegctl register. */
/* Of course the IMM bit is not in that register so it must be */
/* masked out */
#define EE_FORCE_FDX 0x8000
#define EE_NLP_ENABLE 0x0200
#define EE_AUTO_NEG_ENABLE 0x0100
#define EE_ALLOW_FDX 0x0080
#define EE_AUTO_NEG_CNF_MASK (EE_FORCE_FDX|EE_NLP_ENABLE|EE_AUTO_NEG_ENABLE|EE_ALLOW_FDX)
#define IMM_BIT 0x0040 /* ignore missing media */
#define ADAPTER_CNF_OFFSET (AUTO_NEG_CNF_OFFSET + 2)
#define A_CNF_10B_T 0x0001
#define A_CNF_AUI 0x0002
#define A_CNF_10B_2 0x0004
#define A_CNF_MEDIA_TYPE 0x0060
#define A_CNF_MEDIA_AUTO 0x0000
#define A_CNF_MEDIA_10B_T 0x0020
#define A_CNF_MEDIA_AUI 0x0040
#define A_CNF_MEDIA_10B_2 0x0060
#define A_CNF_DC_DC_POLARITY 0x0080
#define A_CNF_NO_AUTO_POLARITY 0x2000
#define A_CNF_LOW_RX_SQUELCH 0x4000
#define A_CNF_EXTND_10B_2 0x8000
#define PACKET_PAGE_OFFSET 0x8
/* Bit definitions for the ISA configuration word from the EEPROM */
#define INT_NO_MASK 0x000F
#define DMA_NO_MASK 0x0070
#define ISA_DMA_SIZE 0x0200
#define ISA_AUTO_RxDMA 0x0400
#define ISA_RxDMA 0x0800
#define DMA_BURST 0x1000
#define STREAM_TRANSFER 0x2000
#define ANY_ISA_DMA (ISA_AUTO_RxDMA | ISA_RxDMA)
/* DMA controller registers */
#define DMA_BASE 0x00 /* DMA controller base */
#define DMA_BASE_2 0x0C0 /* DMA controller base */
#define DMA_STAT 0x0D0 /* DMA controller status register */
#define DMA_MASK 0x0D4 /* DMA controller mask register */
#define DMA_MODE 0x0D6 /* DMA controller mode register */
#define DMA_RESETFF 0x0D8 /* DMA controller first/last flip flop */
/* DMA data */
#define DMA_DISABLE 0x04 /* Disable channel n */
#define DMA_ENABLE 0x00 /* Enable channel n */
/* Demand transfers, incr. address, auto init, writes, ch. n */
#define DMA_RX_MODE 0x14
/* Demand transfers, incr. address, auto init, reads, ch. n */
#define DMA_TX_MODE 0x18
#define DMA_SIZE (16*1024) /* Size of dma buffer - 16k */
#define CS8900 0x0000
#define CS8920 0x4000
#define CS8920M 0x6000
#define REVISON_BITS 0x1F00
#define EEVER_NUMBER 0x12
#define CHKSUM_LEN 0x14
#define CHKSUM_VAL 0x0000
#define START_EEPROM_DATA 0x001c /* Offset into eeprom for start of data */
#define IRQ_MAP_EEPROM_DATA 0x0046 /* Offset into eeprom for the IRQ map */
#define IRQ_MAP_LEN 0x0004 /* No of bytes to read for the IRQ map */
#define PNP_IRQ_FRMT 0x0022 /* PNP small item IRQ format */
#define CS8900_IRQ_MAP 0x1c20 /* This IRQ map is fixed */
#define CS8920_NO_INTS 0x0F /* Max CS8920 interrupt select # */
#define PNP_ADD_PORT 0x0279
#define PNP_WRITE_PORT 0x0A79
#define GET_PNP_ISA_STRUCT 0x40
#define PNP_ISA_STRUCT_LEN 0x06
#define PNP_CSN_CNT_OFF 0x01
#define PNP_RD_PORT_OFF 0x02
#define PNP_FUNCTION_OK 0x00
#define PNP_WAKE 0x03
#define PNP_RSRC_DATA 0x04
#define PNP_RSRC_READY 0x01
#define PNP_STATUS 0x05
#define PNP_ACTIVATE 0x30
#define PNP_CNF_IO_H 0x60
#define PNP_CNF_IO_L 0x61
#define PNP_CNF_INT 0x70
#define PNP_CNF_DMA 0x74
#define PNP_CNF_MEM 0x48
#define BIT0 1
#define BIT15 0x8000
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

800
netboot/eepro100.c Normal file
View file

@ -0,0 +1,800 @@
/*
* eepro100.c -- This file implements the eepro100 driver for etherboot.
*
*
* Copyright (C) AW Computer Systems.
* written by R.E.Wolff -- R.E.Wolff@BitWizard.nl
*
*
* AW Computer Systems is contributing to the free software community
* by paying for this driver and then putting the result under GPL.
*
* If you need a Linux device driver, please contact BitWizard for a
* quote.
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* date version by what
* Written: May 29 1997 V0.10 REW Initial revision.
* changes: May 31 1997 V0.90 REW Works!
* Jun 1 1997 V0.91 REW Cleanup
* Jun 2 1997 V0.92 REW Add some code documentation
* Jul 25 1997 V1.00 REW Tested by AW to work in a PROM
* Cleanup for publication
*
* This is the etherboot-3.1 compatible intel etherexpress Pro/100B
* driver.
*
* It was written from scratch, with Donald Beckers eepro100.c kernel
* driver as a guideline. Mostly the 82557 related definitions and the
* lower level routines have been cut-and-pasted into this source.
*
* The driver was finished before Intel got the NDA out of the closet.
* I still don't have the docs.
* */
/* Philosophy of this driver.
*
* Probing:
*
* Using a subset of "bios32" and "pci" functions of the linux kernel,
* the pci 82557 chip is detected.
*
*
* Initialization:
*
*
* The chip is then initialized to "know" its ethernet address, and to
* start recieving packets. The Linux driver has a whole transmit and
* recieve ring of buffers. This is neat if you need high performance:
* you can write the buffers asynchronously to the chip reading the
* buffers and transmitting them over the network. Performance is NOT
* an issue here. We can boot a 400k kernel in about two
* seconds. (Theory: 0.4 seconds). Booting a system is going to take
* about half a minute anyway, so getting 10 times closer to the
* theoretical limit is going to make a difference of a few percent.
*
*
* Transmitting and recieving.
*
* We have only one transmit descriptor. It has two buffer descriptors:
* one for the header, and the other for the data.
* We have only one receive buffer. The chip is told to recieve packets,
* and suspend itself once it got one. The recieve (poll) routine simply
* looks at the recieve buffer to see if there is already a packet there.
* if there is, the buffer is copied, and the reciever is restarted.
*
* Caveats:
*
* The etherboot framework moves the code to the 32k segment from
* 0x98000 to 0xa0000. There is just a little room between the end of
* this driver and the 0xa0000 address. If you compile in too many
* features, this will overflow.
* The number under "hex" in the output of size that scrolls by while
* compiling should be less than 8000. Maybe even the stack is up there,
* so that you need even more headroom.
*
* If you run into trouble, the method used to give "pci.c" dynamic
* allocation should be used to allocate the larger variables (like
* the packet buffers)
* */
#ifdef INCLUDE_EEPRO100
/* The etherboot authors seem to dislike the argument ordering in
* outb macros that Linux uses. I disklike the confusion that this
* has caused even more.... This file uses the Linux argument ordering. */
#define LINUX_OUT_MACROS
#include "netboot.h"
#include "nic.h"
#include <linux/bios32.h>
#include <linux/pci.h>
static int ioaddr;
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
enum speedo_offsets {
SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */
SCBPointer = 4, /* General purpose pointer. */
SCBPort = 8, /* Misc. commands and operands. */
SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
SCBCtrlMDI = 16, /* MDI interface control. */
SCBEarlyRx = 20, /* Early receive byte count. */
};
static int read_eeprom(int ioaddr, int location);
static void udelay (int val);
void hd (void *where, int n);
/***********************************************************************/
/* I82557 related defines */
/***********************************************************************/
/* Serial EEPROM section.
A "bit" grungy, but we work our way through bit-by-bit :->. */
/* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
#define EE_CS 0x02 /* EEPROM chip select. */
#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
#define EE_WRITE_0 0x01
#define EE_WRITE_1 0x05
#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
#define EE_ENB (0x4800 | EE_CS)
/* Delay between EEPROM clock transitions.
This is a "nasty" timing loop, but PC compatible machines are defined
to delay an ISA compatible period for the SLOW_DOWN_IO macro. */
#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) \
{ __SLOW_DOWN_IO; }} while (0)
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6)
#define EE_READ_CMD (6 << 6)
#define EE_ERASE_CMD (7 << 6)
/* The SCB accepts the following controls for the Tx and Rx units: */
#define CU_START 0x0010
#define CU_RESUME 0x0020
#define CU_STATSADDR 0x0040
#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */
#define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */
#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */
#define RX_START 0x0001
#define RX_RESUME 0x0002
#define RX_ABORT 0x0004
#define RX_ADDR_LOAD 0x0006
#define RX_RESUMENR 0x0007
#define INT_MASK 0x0100
#define DRVR_INT 0x0200 /* Driver generated interrupt. */
enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
S80C24, PhyUndefined, DP83840A=10, };
/* Commands that can be put in a command list entry. */
enum commands {
CmdNOp = 0,
CmdIASetup = 1,
CmdConfigure = 2,
CmdMulticastList = 3,
CmdTx = 4,
CmdTDR = 5,
CmdDump = 6,
CmdDiagnose = 7,
/* And some extra flags: */
CmdSuspend = 0x4000, /* Suspend after completion. */
CmdIntr = 0x2000, /* Interrupt after completion. */
CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */
};
/* How to wait for the command unit to accept a command.
Typically this takes 0 ticks. */
static inline void wait_for_cmd_done(int cmd_ioaddr)
{
short wait = 100;
do ;
while(inb(cmd_ioaddr) && --wait >= 0);
}
/* Elements of the dump_statistics block. This block must be lword aligned. */
struct speedo_stats {
u32 tx_good_frames;
u32 tx_coll16_errs;
u32 tx_late_colls;
u32 tx_underruns;
u32 tx_lost_carrier;
u32 tx_deferred;
u32 tx_one_colls;
u32 tx_multi_colls;
u32 tx_total_colls;
u32 rx_good_frames;
u32 rx_crc_errs;
u32 rx_align_errs;
u32 rx_resource_errs;
u32 rx_overrun_errs;
u32 rx_colls_errs;
u32 rx_runt_errs;
u32 done_marker;
} lstats;
/* A speedo3 TX buffer descriptor with two buffers... */
struct TxFD {
volatile s16 status;
s16 command;
u32 link; /* void * */
u32 tx_desc_addr; /* (almost) Always points to the tx_buf_addr element. */
s32 count; /* # of TBD (=2), Tx start thresh., etc. */
/* This constitutes two "TBD" entries: hdr and data */
u32 tx_buf_addr0; /* void *, header of frame to be transmitted. */
s32 tx_buf_size0; /* Length of Tx hdr. */
u32 tx_buf_addr1; /* void *, data to be transmitted. */
s32 tx_buf_size1; /* Length of Tx data. */
} txfd;
/* The Speedo3 Rx buffer descriptors. */
struct RxFD { /* Receive frame descriptor. */
volatile s16 status;
s16 command;
u32 link; /* struct RxFD * */
u32 rx_buf_addr; /* void * */
u16 count;
u16 size;
char packet[1518];
} rxfd;
static int congenb = 0; /* Enable congestion control in the DP83840. */
static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
static int txdmacount = 0; /* Tx DMA burst length, 0-127, default 0. */
static int rxdmacount = 0; /* Rx DMA length, 0 means no preemption. */
/* I don't understand a byte in this structure. It was copied from the
* Linux kernel initialization for the eepro100. -- REW */
struct ConfCmd {
s16 status;
s16 command;
u32 link;
unsigned char data[22];
} confcmd = {
0, CmdConfigure,
(u32) & txfd,
{22, 0x08, 0, 0, 0, 0x80, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */
0, 0x2E, 0, 0x60, 0,
0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */
0x3f, 0x05, }
};
#define TIME_OUT 1000000
/* The "pci" code needs to allocate a few structures. It wants to
* increment the "kernel memory ends here" pointer to allocate memory.
* I guess that a machine with PCI has more than 2Mb of memory, so
* that is where those things are put. Those structures don't survive
* the "jump to kernel start".
* */
#define MEM_START 0x200000 /* Memory starts at 2Mb for now.... */
#define MEM_END 0
static unsigned short eeprom [0x40];
static void calibrate_delay (void);
/***********************************************************************/
/* Locally used functions */
/***********************************************************************/
/* Support function: mdio_write
*
* This probably writes to the "physical media interface chip".
* -- REW
*/
static int mdio_write(int ioaddr, int phy_id, int location, int value)
{
int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
outl(0x04000000 | (location<<16) | (phy_id<<21) | value,
ioaddr + SCBCtrlMDI);
do {
udelay(16);
val = inl(ioaddr + SCBCtrlMDI);
if (--boguscnt < 0) {
printf(" mdio_write() timed out with val = %8.8x.\n", val);
}
} while (! (val & 0x10000000));
return val & 0xffff;
}
/* Support function: mdio_read
*
* This probably reads a register in the "physical media interface chip".
* -- REW
*/
static int mdio_read(int ioaddr, int phy_id, int location)
{
int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
do {
udelay(16);
val = inl(ioaddr + SCBCtrlMDI);
if (--boguscnt < 0) {
printf( " mdio_read() timed out with val = %8.8x.\n", val);
}
} while (! (val & 0x10000000));
return val & 0xffff;
}
/* Support function: read_eeprom
* reads a value from the eeprom at a specified location.
* Arguments: ioaddr: address of the 82557 chip
* location: address of the location to read from the eeprom.
* returns: value read from eeprom at location.
*/
static int read_eeprom(int ioaddr, int location)
{
int i;
unsigned short retval = 0;
int ee_addr = ioaddr + SCBeeprom;
int read_cmd = location | EE_READ_CMD;
outw(EE_ENB & ~EE_CS, ee_addr);
outw(EE_ENB, ee_addr);
/* Shift the read command bits out. */
for (i = 10; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
outw(EE_ENB | dataval, ee_addr);
eeprom_delay(100);
outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay(150);
outw(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */
eeprom_delay(250);
}
outw(EE_ENB, ee_addr);
for (i = 15; i >= 0; i--) {
outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay(100);
retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
outw(EE_ENB, ee_addr);
eeprom_delay(100);
}
/* Terminate the EEPROM access. */
outw(EE_ENB & ~EE_CS, ee_addr);
return retval;
}
static void inline whereami (char *str)
{
#if 0
printf ("%s\r\n", str);
sleep (2);
#endif
}
/***********************************************************************/
/* Externally visible functions */
/***********************************************************************/
/* function: eepro100_reset / eth_reset
* resets the card. This is used to allow Linux to probe the card again
* from a "virginal" state....
* Arguments: none
*
* returns: void.
*/
static void eepro100_reset(struct nic *nic)
{
outl(0, ioaddr + SCBPort);
}
/* function: eepro100_transmit / eth_transmit
* This transmits a packet.
*
* Arguments: char d[6]: destination ethernet address.
* unsigned short t: ethernet protocol type.
* unsigned short s: size of the data-part of the packet.
* char *p: the data for the packet.
* returns: void.
*/
static void eepro100_transmit(struct nic *nic, char *d, unsigned int t, unsigned int s, char *p)
{
struct eth_hdr {
unsigned char dst_addr[6];
unsigned char src_addr[6];
unsigned short type;
} hdr;
unsigned short status;
int to;
int s1, s2;
status = inw(ioaddr + SCBStatus);
/* Acknowledge all of the current interrupt sources ASAP. */
outw(status & 0xfc00, ioaddr + SCBStatus);
#ifdef DEBUG
printf ("transmitting type %x packet (%d bytes). status = %x, cmd=%x\r\n",
t, s, status, inw (ioaddr + SCBCmd));
#endif
memcpy (&hdr.dst_addr, d, 6);
memcpy (&hdr.src_addr, &arptable[ARP_CLIENT].node, 6);
hdr.type = htons (t);
txfd.status = 0;
txfd.command = CmdSuspend | CmdTx | CmdTxFlex;
txfd.link = virt_to_bus (&txfd);
txfd.count = 0x02208000;
txfd.tx_desc_addr = (u32)&txfd.tx_buf_addr0;
txfd.tx_buf_addr0 = virt_to_bus (&hdr);
txfd.tx_buf_size0 = sizeof (hdr);
txfd.tx_buf_addr1 = virt_to_bus (p);
txfd.tx_buf_size1 = s;
#ifdef DEBUG
printf ("txfd: \r\n");
hd (&txfd, sizeof (txfd));
#endif
outl(virt_to_bus(&txfd), ioaddr + SCBPointer);
outw(INT_MASK | CU_START, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
s1 = inw (ioaddr + SCBStatus);
to = TIME_OUT;
while (!txfd.status && --to)
/* Wait */;
s2 = inw (ioaddr + SCBStatus);
#ifdef DEBUG
printf ("Tx: Loop executed %d times.\r\n", TIME_OUT-to);
printf ("s1 = %x, s2 = %x.\r\n", s1, s2);
#endif
}
/* function: eepro100_poll / eth_poll
* This recieves a packet from the network.
*
* Arguments: none
*
* returns: 1 if a packet was recieved.
* 0 if no pacet was recieved.
* side effects:
* returns the packet in the array nic->packet.
* returns the length of the packet in nic->packetlen.
*/
static int eepro100_poll(struct nic *nic)
{
int to;
to = TIME_OUT;
while (!rxfd.status && --to)
/* Wait */;
/* Ok. We got a packet. Now restart the reciever.... */
rxfd.status = 0;
rxfd.command = 0xc000;
outl(virt_to_bus(&rxfd), ioaddr + SCBPointer);
outw(INT_MASK | RX_START, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
if (to) {
#ifdef DEBUG
printf ("Got a packet: Len = %d.\r\n", rxfd.count & 0x3fff);
#endif
nic->packetlen = rxfd.count & 0x3fff;
bcopy (rxfd.packet, nic->packet, sizeof (rxfd.packet));
#ifdef DEBUG
hd (nic->packet, 0x30);
#endif
return 1;
} else
return 0;
}
static void eepro100_disable(struct nic *nic)
{
}
/* exported function: eepro100_probe / eth_probe
* initializes a card
*
* side effects:
* leaves the ioaddress of the 82557 chip in the variable ioaddr.
* leaves the 82557 initialized, and ready to recieve packets.
*/
struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs)
{
int pci_index;
u16 sum = 0;
int i, j, to;
unsigned short value;
int options;
int promisc;
if (probeaddrs == 0 || probeaddrs[0] == 0)
return 0;
ioaddr = probeaddrs[0] & ~3; /* Mask the bit that says "this is an io addr" */
/* Ok. Got one. Read the eeprom. */
for (j = 0, i = 0; i < 0x40; i++) {
value = read_eeprom(ioaddr, i);
eeprom[i] = value;
sum += value;
}
printf ("Ethernet addr: ");
for (i=0;i<6;i++) {
arptable[ARP_CLIENT].node[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
printf ("%b%c", arptable[ARP_CLIENT].node[i] , i < 5?':':' ');
}
printf ("\r\n");
if (sum != 0xBABA)
printf("eepro100: Invalid EEPROM checksum %#4.4x, "
"check settings before activating this device!\r\n", sum);
outl(0, ioaddr + SCBPort);
udelay (10);
whereami ("Got eeprom.");
outl(virt_to_bus(&lstats), ioaddr + SCBPointer);
outw(INT_MASK | CU_STATSADDR, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
whereami ("set stats addr.");
/* INIT RX stuff. */
/* Base = 0 */
outl(0, ioaddr + SCBPointer);
outw(INT_MASK | RX_ADDR_LOAD, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
whereami ("set rx base addr.");
rxfd.status = 0x0001;
rxfd.command = 0x0000;
rxfd.link = virt_to_bus(&rxfd);
rxfd.rx_buf_addr = (int) &nic->packet;
rxfd.count = 0;
rxfd.size = 1528;
outl(virt_to_bus(&rxfd), ioaddr + SCBPointer);
outw(INT_MASK | RX_START, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
whereami ("started RX process.");
/* Start the reciever.... */
rxfd.status = 0;
rxfd.command = 0xc000;
outl(virt_to_bus(&rxfd), ioaddr + SCBPointer);
outw(INT_MASK | RX_START, ioaddr + SCBCmd);
/* INIT TX stuff. */
/* Base = 0 */
outl(0, ioaddr + SCBPointer);
outw(INT_MASK | CU_CMD_BASE, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
whereami ("set TX base addr.");
txfd.command = (CmdIASetup);
txfd.status = 0x0000;
txfd.link = virt_to_bus (&confcmd);
{
char *p = (char *)&txfd.tx_desc_addr;
for (i=0;i<6;i++)
p[i] = arptable[ARP_CLIENT].node[i];
}
#ifdef DEBUG
printf ("Setup_eaddr:\r\n");
hd (&txfd, 0x20);
#endif
/* options = 0x40; */ /* 10mbps half duplex... */
options = 0x00; /* Autosense */
promisc = 0;
printf ("eeprom[6] = %x \r\n", eeprom[6]);
if ( ((eeprom[6]>>8) & 0x3f) == DP83840
|| ((eeprom[6]>>8) & 0x3f) == DP83840A) {
int mdi_reg23 = mdio_read(ioaddr, eeprom[6] & 0x1f, 23) | 0x0422;
if (congenb)
mdi_reg23 |= 0x0100;
printf(" DP83840 specific setup, setting register 23 to %x.\r\n",
mdi_reg23);
mdio_write(ioaddr, eeprom[6] & 0x1f, 23, mdi_reg23);
}
whereami ("Done DP8340 special setup.");
if (options != 0) {
mdio_write(ioaddr, eeprom[6] & 0x1f, 0,
((options & 0x20) ? 0x2000 : 0) | /* 100mbps? */
((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */
whereami ("set mdio_register.");
}
confcmd.command = CmdSuspend | CmdConfigure;
confcmd.status = 0x0000;
confcmd.link = virt_to_bus (&txfd);
confcmd.data[1] = (txfifo << 4) | rxfifo;
confcmd.data[4] = rxdmacount;
confcmd.data[5] = txdmacount + 0x80;
confcmd.data[15] = promisc ? 0x49: 0x48;
confcmd.data[19] = (options & 0x10) ? 0xC0 : 0x80;
confcmd.data[21] = promisc ? 0x0D: 0x05;
outl(virt_to_bus(&txfd), ioaddr + SCBPointer);
outw(INT_MASK | CU_START, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
whereami ("started TX thingy (config, iasetup).");
to = TIME_OUT;
while (!txfd.status && --to)
/* Wait */;
#ifdef DEBUG
printf ("\r\nLoop executed %d times.\r\n", TIME_OUT-to);
#endif
nic->reset = eepro100_reset;
nic->poll = eepro100_poll;
nic->transmit = eepro100_transmit;
nic->disable = eepro100_disable;
return nic;
}
static int loops_per_sec;
static int loops_per_usec;
static void udelay (int val)
{
int c;
for(c=0; c<val*loops_per_usec; c++) {
/* Nothing */;
}
}
#if 1
/* I don't have the possibility to test the below code. Murphey tells me
* it won't work.
*/
static void calibrate_delay (void)
{
loops_per_usec = 500;
}
#else
#define __delay udelay
#define jiffies currticks()
#define HZ 18
#define LPS_PREC 8
/* Copied from /usr/src/linux/init/main.c */
/* with just a few modifications. */
void calibrate_delay (void)
{
int ticks;
int loopbit;
int lps_precision = LPS_PREC;
loops_per_sec = (1<<12);
loops_per_usec = 1;
printk("Calibrating delay loop.. ");
while (loops_per_sec <<= 1) {
/* wait for "start of" clock tick */
ticks = jiffies;
while (ticks == jiffies)
/* nothing */;
/* Go .. */
ticks = jiffies;
__delay(loops_per_sec);
ticks = jiffies - ticks;
if (ticks)
break;
}
/* Do a binary approximation to get loops_per_second set to equal one clock
(up to lps_precision bits) */
loops_per_sec >>= 1;
loopbit = loops_per_sec;
while ( lps_precision-- && (loopbit >>= 1) ) {
loops_per_sec |= loopbit;
ticks = jiffies;
while (ticks == jiffies);
ticks = jiffies;
__delay(loops_per_sec);
if (jiffies != ticks) /* longer than 1 tick */
loops_per_sec &= ~loopbit;
}
/* finally, adjust loops per second in terms of seconds instead of clocks */
loops_per_sec *= HZ;
/* Round the value and print it */
printk("ok - %d.%d BogoMIPS\n",
(loops_per_sec+25000)/500000,
((loops_per_sec+25000)/50000) % 10);
loops_per_usec = loops_per_sec / 1000000;
}
#endif
/*********************************************************************/
#ifdef DEBUG
/* Hexdump a number of bytes from memory... */
void hd (void *where, int n)
{
int i;
while (n > 0) {
printf ("%X ", where);
for (i=0;i < ( (n>16)?16:n);i++)
printf (" %b", ((char *)where)[i]);
printf ("\n\r");
n -= 16;
where += 16;
}
}
#endif
#endif /* INCLUDE_EEPRO100 */

227
netboot/fsys_tftp.c Normal file
View file

@ -0,0 +1,227 @@
#include "../stage2/filesys.h"
#include "netboot.h"
#include "config.h"
#include "nic.h"
#include "ip.h"
#if 0
#define BUFSIZE (20*TFTP_DEFAULTSIZE_PACKET)
static char buf[BUFSIZE];
#else
/* use GRUB's file system buffer */
#define BUFSIZE (32*1024)
#define buf ((char *)(FSYS_BUF))
#endif
static int buf_read = 0, buf_eof = 0;
static unsigned long buf_fileoff;
static int retry;
static unsigned short isocket = 2000;
static unsigned short osocket;
static unsigned short len, block, prevblock;
static struct tftp_t *tr;
static struct tftp_t tp;
static int packetsize = TFTP_DEFAULTSIZE_PACKET;
static int buf_fill(int abort);
int tftp_mount(void)
{
if (current_drive != 0x20) /* only mount network drives */
return 0;
if (!ip_init())
return 0;
return 1;
}
/* read "size" bytes from file position "filepos" to "addr" */
int tftp_read(char *addr, int size)
{
int ret = 0;
if (filepos < buf_fileoff)
{
printf("tftp_read: can't read from filepos=%d, buf_fileoff=%d\n",
filepos, buf_fileoff);
errnum = ERR_BOOT_FAILURE;
return 0;
}
while (size > 0)
{
if (filepos < buf_fileoff + buf_read)
{
/* can copy stuff from buffer */
int tocopy = buf_fileoff + buf_read - filepos;
if (tocopy > size) tocopy = size;
bcopy(buf + (filepos - buf_fileoff), (void*) addr, tocopy);
size -= tocopy;
addr += tocopy;
filepos += tocopy;
ret += tocopy;
if (buf_eof && (filepos + size >= buf_fileoff + buf_read))
break; /* end of file */
continue;
}
else if ((filepos == buf_fileoff + buf_read) && buf_eof)
break; /* end of file */
if (buf_eof) /* filepos beyond end of file */
{
errnum = ERR_READ;
return 0;
}
/* move buffer contents forward by 1/2 buffer size */
bcopy(buf + BUFSIZE/2, buf, BUFSIZE/2);
buf_fileoff += BUFSIZE/2;
buf_read -= BUFSIZE/2;
if (! buf_fill(0)) /* read more data */
{
errnum = ERR_READ;
return 0;
}
}
return ret;
}
int tftp_dir(char *dirname)
{
char name[100], *np;
if (print_possibilities)
{
printf(" TFTP doesn't support listing the directory; Sorry!\n");
return 1;
}
/* open the file */
np = name;
while (dirname && *dirname && !isspace(*dirname))
*np++ = *dirname++;
*np = 0;
buf_eof = buf_read = buf_fileoff = 0;
retry = 0;
block = 0;
prevblock = 0;
packetsize = TFTP_DEFAULTSIZE_PACKET;
/* send tftp read request */
tp.opcode = htons(TFTP_RRQ);
len = 30 + sprintf((char *)tp.u.rrq, "%s%coctet%cblksize%c%d",
name, 0, 0, 0, TFTP_MAX_PACKET) + 1;
if (!udp_transmit(arptable[ARP_SERVER].ipaddr, ++isocket, TFTP,
len, (char *)&tp))
{
printf("tftp_dir: can't transmit TFTP read request\n");
errnum = ERR_BOOT_FAILURE;
return (0);
}
if (! buf_fill(0))
{
printf("tftp_dir: can't read from file\n");
errnum = ERR_FILE_NOT_FOUND;
return 0;
}
/* filemax = 234620; */
filemax = 16L*1024*1024; /* XXX 16MB is max filesize */
return 1;
}
#if 0
void tftp_close(void)
{
buf_read = 0;
buf_fill(1); /* abort. */
}
#endif
static int buf_fill(int abort)
{
while (!buf_eof && (buf_read + packetsize <= BUFSIZE))
{
/* read a packet from the network */
if (!await_reply(AWAIT_TFTP, isocket, NULL))
{
if (ip_abort)
return 0;
if (prevblock == 0 && retry++ < MAX_TFTP_RETRIES)
{ /* maybe initial request was lost */
rfc951_sleep(retry);
if (!udp_transmit(arptable[ARP_SERVER].ipaddr,
++isocket, TFTP, len, (char *)&tp))
return (0);
continue;
}
return 0; /* timeout on other blocks */
}
/* we got a packet */
tr = (struct tftp_t *)&nic.packet[ETHER_HDR_SIZE];
if (tr->opcode == ntohs(TFTP_ERROR)) /* error? */
{
printf("TFTP error %d (%s)\r\n",
ntohs(tr->u.err.errcode),
tr->u.err.errmsg);
return 0;
}
else if (tr->opcode == ntohs(TFTP_OACK))
{
continue; /* ignore */
}
else if (tr->opcode == ntohs(TFTP_DATA))
{
retry = MAX_TFTP_RETRIES; /*no more retries! */
len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;
if (len > packetsize) /* shouldn't happen */
continue; /* ignore it */
block = ntohs(tp.u.ack.block = tr->u.data.block);
}
else /* neither TFTP_OACK nor TFTP_DATA */
return 0;
tp.opcode = abort ? htons(TFTP_ERROR) : htons(TFTP_ACK);
osocket = ntohs(tr->udp.src);
udp_transmit(arptable[ARP_SERVER].ipaddr, isocket,
osocket, TFTP_MIN_PACKET, (char *)&tp); /* ack */
if (abort)
{
buf_eof = 1;
break;
}
if (block <= prevblock) /* retransmission or OACK */
continue; /* don't process */
prevblock = block;
bcopy(tr->u.data.download, buf + buf_read, len);
buf_read += len;
if (len < packetsize) /* End of data */
buf_eof = 1;
}
return 1;
}

18
netboot/if.h Normal file
View file

@ -0,0 +1,18 @@
/* Standard interface flags. */
#define IFF_UP 0x1 /* interface is up */
#define IFF_BROADCAST 0x2 /* broadcast address valid */
#define IFF_DEBUG 0x4 /* turn on debugging */
#define IFF_LOOPBACK 0x8 /* is a loopback net */
#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
#define IFF_RUNNING 0x40 /* resources allocated */
#define IFF_NOARP 0x80 /* no ARP protocol */
#define IFF_PROMISC 0x100 /* receive all packets */
/* Not supported */
#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
#define IFF_MASTER 0x400 /* master of a load balancer */
#define IFF_SLAVE 0x800 /* slave of a load balancer */
#define IFF_MULTICAST 0x1000 /* Supports multicast */

93
netboot/io.h Normal file
View file

@ -0,0 +1,93 @@
#ifndef _ASM_IO_H
#define _ASM_IO_H
/*
* This file contains parts of Linux's /usr/include/asm/io.h, but
* with the argument order reversed for outb, outb_p, outw, outw_p.
*/
#define SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
#define __OUT1(s,x) \
extern inline void __out##s(unsigned x value, unsigned short port); \
extern inline void __out##s(unsigned x value, unsigned short port) {
#define __OUT2(s,s1,s2) \
__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
#define __OUT(s,s1,x) \
__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); } \
__OUT1(s##c,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); } \
__OUT1(s##_p,x) __OUT2(s,s1,"w") : : "a" (value), "d" (port)); SLOW_DOWN_IO; } \
__OUT1(s##c_p,x) __OUT2(s,s1,"") : : "a" (value), "id" (port)); SLOW_DOWN_IO; }
#define __IN1(s) \
extern inline RETURN_TYPE __in##s(unsigned short port); \
extern inline RETURN_TYPE __in##s(unsigned short port) { RETURN_TYPE _v;
#define __IN2(s,s1,s2) \
__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
#define __IN(s,s1,i...) \
__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \
__IN1(s##c) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \
__IN1(s##_p) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \
__IN1(s##c_p) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; }
#define RETURN_TYPE unsigned char
/* __IN(b,"b","0" (0)) */
__IN(b,"")
#undef RETURN_TYPE
#define RETURN_TYPE unsigned short
/* __IN(w,"w","0" (0)) */
__IN(w,"")
#undef RETURN_TYPE
#define RETURN_TYPE unsigned int
__IN(l,"")
#undef RETURN_TYPE
__OUT(b,"b",char)
__OUT(w,"w",short)
__OUT(l,,int)
#define outb(port,val) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outbc((val),(port)) : \
__outb((val),(port)))
#define inb(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inbc(port) : \
__inb(port))
#define outb_p(port,val) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outbc_p((val),(port)) : \
__outb_p((val),(port)))
#define inb_p(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inbc_p(port) : \
__inb_p(port))
#define outw(port,val) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outwc((val),(port)) : \
__outw((val),(port)))
#define inw(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inwc(port) : \
__inw(port))
#define outw_p(port,val) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__outwc_p((val),(port)) : \
__outw_p((val),(port)))
#define inw_p(port) \
((__builtin_constant_p((port)) && (port) < 256) ? \
__inwc_p(port) : \
__inw_p(port))
#endif

645
netboot/ip.c Normal file
View file

@ -0,0 +1,645 @@
#include "netboot.h"
#include "config.h"
#include "nic.h"
#include "ip.h"
struct arptable_t arptable[MAX_ARP];
int _pending_key;
static unsigned long netmask;
static char rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
static char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static char *kernel;
static char kernel_buf[128];
static struct bootpd_t bootp_data;
static int vendorext_isvalid;
static unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* äEth */
static unsigned char *end_of_rfc1533 = NULL;
int ip_abort = 0;
static int bootp(void);
static void default_netmask(void);
static void convert_ipaddr(register char *d, register char *s);
static int decode_rfc1533(register unsigned char *p, int block, int len,
int eof);
int ip_init(void)
{
static int bootp_completed = 0,
probe_completed = 0;
if (!probe_completed && !eth_probe())
{
printf("No ethernet adapter found\n");
return 0;
}
probe_completed = 1;
#if 1
if ((!bootp_completed ||
!arptable[ARP_CLIENT].ipaddr || !arptable[ARP_SERVER].ipaddr))
{
#endif
if (!bootp())
{
printf("No BOOTP server found\n");
return 0;
}
printf("My IP 0x%x, Server IP 0x%x, GW IP 0x%x\n",
arptable[ARP_CLIENT].ipaddr,
arptable[ARP_SERVER].ipaddr,
arptable[ARP_GATEWAY].ipaddr);
#ifdef CONFIG_FILE_EXT
{
char *ext = &config_file;
/* seek to end of config file name */
while(*ext)
ext++;
sprintf(ext, ".%d", arptable[ARP_CLIENT].ipaddr & 0xff);
}
#endif
#if 1
}
bootp_completed = 1;
#endif
return 1;
}
/**************************************************************************
UDP_TRANSMIT - Send a UDP datagram
**************************************************************************/
int udp_transmit(destip, srcsock, destsock, len, buf)
unsigned long destip;
unsigned int srcsock, destsock;
int len;
char *buf;
{
struct iphdr *ip;
struct udphdr *udp;
struct arprequest arpreq;
int arpentry, i;
int retry;
ip = (struct iphdr *)buf;
udp = (struct udphdr *)(buf + sizeof(struct iphdr));
ip->verhdrlen = 0x45;
ip->service = 0;
ip->len = htons(len);
ip->ident = 0;
ip->frags = 0;
ip->ttl = 60;
ip->protocol = IP_UDP;
ip->chksum = 0;
convert_ipaddr(ip->src, (char *)&arptable[ARP_CLIENT].ipaddr);
convert_ipaddr(ip->dest, (char *)&destip);
ip->chksum = ipchksum((unsigned short *)buf, sizeof(struct iphdr));
udp->src = htons(srcsock);
udp->dest = htons(destsock);
udp->len = htons(len - sizeof(struct iphdr));
udp->chksum = 0;
if (destip == IP_BROADCAST) {
eth_transmit(broadcast, IP, len, buf);
} else {
long h_netmask = ntohl(netmask);
/* Check to see if we need gateway */
if (((destip & h_netmask) !=
(arptable[ARP_CLIENT].ipaddr & h_netmask)) &&
arptable[ARP_GATEWAY].ipaddr)
destip = arptable[ARP_GATEWAY].ipaddr;
for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
if (arptable[arpentry].ipaddr == destip) break;
if (arpentry == MAX_ARP) {
printf("%I is not in my arp table!\r\n", destip);
return(0);
}
for (i = 0; i<ETHER_ADDR_SIZE; i++)
if (arptable[arpentry].node[i]) break;
if (i == ETHER_ADDR_SIZE) { /* Need to do arp request */
arpreq.hwtype = htons(1);
arpreq.protocol = htons(IP);
arpreq.hwlen = ETHER_ADDR_SIZE;
arpreq.protolen = 4;
arpreq.opcode = htons(ARP_REQUEST);
bcopy(arptable[ARP_CLIENT].node, arpreq.shwaddr,
ETHER_ADDR_SIZE);
convert_ipaddr(arpreq.sipaddr,
(char *)&arptable[ARP_CLIENT].ipaddr);
bzero(arpreq.thwaddr, ETHER_ADDR_SIZE);
convert_ipaddr(arpreq.tipaddr, (char *)&destip);
for (retry = 0; retry < MAX_ARP_RETRIES;
rfc951_sleep(++retry)) {
eth_transmit(broadcast, ARP, sizeof(arpreq),
(char *)&arpreq);
if (await_reply(AWAIT_ARP, arpentry,
arpreq.tipaddr)) goto xmit;
if (ip_abort)
return 0;
}
return(0);
}
xmit: eth_transmit(arptable[arpentry].node, IP, len, buf);
}
return(1);
}
/**************************************************************************
AWAIT_REPLY - Wait until we get a response for our request
**************************************************************************/
int await_reply(type, ival, ptr)
int type, ival;
char *ptr;
{
unsigned long time;
struct iphdr *ip;
struct udphdr *udp;
struct arprequest *arpreply;
struct bootp_t *bootpreply;
struct rpc_t *rpc;
int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) +
sizeof(struct udphdr);
ip_abort = 0;
time = currticks() + TIMEOUT;
while(time > currticks()) {
#if 0
if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1);
#else
if (iskey() && (getchar() == ESC))
{
ip_abort = 1;
return 0;
}
#endif
if (eth_poll())
{ /* We have something! */
/* Check for ARP - No IP hdr */
if ((nic.packetlen >= ETHER_HDR_SIZE +
sizeof(struct arprequest)) &&
(((nic.packet[12] << 8) | nic.packet[13]) == ARP))
{
unsigned long target_ip;
arpreply = (struct arprequest *)
&nic.packet[ETHER_HDR_SIZE];
if (arpreply->opcode == ntohs(ARP_REQUEST)
&& (convert_ipaddr(&target_ip,
&arpreply->tipaddr),
arptable[ARP_CLIENT].ipaddr == target_ip))
{
/* request for our ether address -- send a reply */
unsigned long my_ip_net
= *(unsigned long*)(arpreply->tipaddr);
bcopy(arpreply->shwaddr, arpreply->thwaddr, 10);
bcopy(arptable[ARP_CLIENT].node,
arpreply->shwaddr, ETHER_ADDR_SIZE);
*(unsigned long*)(arpreply->sipaddr) = my_ip_net;
arpreply->opcode = htons(ARP_REPLY);
eth_transmit(arpreply->thwaddr, ARP,
sizeof(struct arprequest),
(char *) arpreply);
continue;
}
else if (type == AWAIT_ARP &&
(arpreply->opcode == ntohs(ARP_REPLY)) &&
!bcmp(arpreply->sipaddr, ptr, 4)) {
bcopy(arpreply->shwaddr,
arptable[ival].node,
ETHER_ADDR_SIZE);
return(1);
}
continue;
}
/* Anything else has IP header */
if ((nic.packetlen < protohdrlen) ||
(((nic.packet[12] << 8) | nic.packet[13]) != IP)) continue;
ip = (struct iphdr *)&nic.packet[ETHER_HDR_SIZE];
if ((ip->verhdrlen != 0x45) ||
ipchksum((unsigned short *)ip, sizeof(struct iphdr)) ||
(ip->protocol != IP_UDP)) continue;
udp = (struct udphdr *)&nic.packet[ETHER_HDR_SIZE +
sizeof(struct iphdr)];
/* BOOTP ? */
bootpreply = (struct bootp_t *)&nic.packet[ETHER_HDR_SIZE];
if ((type == AWAIT_BOOTP) &&
(nic.packetlen >= (ETHER_HDR_SIZE +
sizeof(struct bootp_t))) &&
(ntohs(udp->dest) == BOOTP_CLIENT) &&
(bootpreply->bp_op == BOOTP_REPLY)) {
convert_ipaddr((char *)&arptable[ARP_CLIENT].ipaddr,
bootpreply->bp_yiaddr);
default_netmask();
convert_ipaddr((char *)&arptable[ARP_SERVER].ipaddr,
bootpreply->bp_siaddr);
bzero(arptable[ARP_SERVER].node,
ETHER_ADDR_SIZE); /* Kill arp */
convert_ipaddr((char *)&arptable[ARP_GATEWAY].ipaddr,
bootpreply->bp_giaddr);
bzero(arptable[ARP_GATEWAY].node,
ETHER_ADDR_SIZE); /* Kill arp */
if (bootpreply->bp_file[0]) {
bcopy(bootpreply->bp_file,
kernel_buf, 128);
kernel = kernel_buf;
}
bcopy((char *)bootpreply,
(char *)&bootp_data,
sizeof(struct bootp_t));
decode_rfc1533(bootp_data.bootp_reply.bp_vend,
0, BOOTP_VENDOR_LEN, 1);
return(1);
}
/* TFTP ? */
if ((type == AWAIT_TFTP) &&
(ntohs(udp->dest) == ival)) return(1);
/* RPC */
rpc = (struct rpc_t *)&nic.packet[ETHER_HDR_SIZE];
#ifdef NFS_BOOT
if ((type == AWAIT_RPC) &&
(ntohs(udp->dest) == RPC_SOCKET) &&
(ntohl(rpc->u.reply.id) == ival) &&
(ntohl(rpc->u.reply.type) == MSG_REPLY)) {
rpc_id++;
return(1);
}
#endif /* NFS_BOOT */
}
}
return(0);
}
/**************************************************************************
IPCHKSUM - Checksum IP Header
**************************************************************************/
unsigned short ipchksum(ip, len)
register unsigned short *ip;
register int len;
{
unsigned long sum = 0;
len >>= 1;
while (len--) {
sum += *(ip++);
if (sum > 0xFFFF)
sum -= 0xFFFF;
}
return((~sum) & 0x0000FFFF);
}
/**************************************************************************
TFTP - Download extended BOOTP data, configuration file or kernel image
**************************************************************************/
int tftp(name,fnc)
char *name;
int (*fnc)(unsigned char *, int, int, int);
{
int retry = 0;
static unsigned short isocket = 2000;
unsigned short osocket;
unsigned short len, block = 0, prevblock = 0;
struct tftp_t *tr;
struct tftp_t tp;
int rc;
int packetsize = TFTP_DEFAULTSIZE_PACKET;
tp.opcode = htons(TFTP_RRQ);
len = 30 + sprintf((char *)tp.u.rrq, "%s%coctet%cblksize%c%d",
name, 0, 0, 0, TFTP_MAX_PACKET) + 1;
if (!udp_transmit(arptable[ARP_SERVER].ipaddr, ++isocket, TFTP,
len, (char *)&tp))
return (0);
for (;;)
{
if (!await_reply(AWAIT_TFTP, isocket, NULL))
{
if (ip_abort)
return 0;
if (prevblock == 0 && retry++ < MAX_TFTP_RETRIES)
{ /* maybe initial request was lost */
rfc951_sleep(retry);
if (!udp_transmit(arptable[ARP_SERVER].ipaddr,
++isocket, TFTP, len, (char *)&tp))
return (0);
continue;
}
break; /* timeout on other blocks */
}
tr = (struct tftp_t *)&nic.packet[ETHER_HDR_SIZE];
if (tr->opcode == ntohs(TFTP_ERROR))
{
printf("TFTP error %d (%s)\r\n",
ntohs(tr->u.err.errcode),
tr->u.err.errmsg);
break;
}
if (tr->opcode == ntohs(TFTP_OACK)) {
#if 0
char *p = tr->u.oack.data, *e;
retry = MAX_TFTP_RETRIES;/*no more retries! */
if (prevblock) /* shouldn't happen */
continue; /* ignore it */
len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 2;
if (len > TFTP_MAX_PACKET)
goto noak;
e = p + len;
while (*p != '\000' && p < e) {
if (!strcasecmp("blksize", p)) {
p += 8;
if ((packetsize = getdec(&p)) <
TFTP_DEFAULTSIZE_PACKET)
goto noak;
while (p < e && *p) p++;
if (p < e)
p++;
}
else {
noak:
tp.opcode = htons(TFTP_ERROR);
tp.u.err.errcode = 8;
len = 30 + sprintf((char *)tp.u.err.errmsg,
"RFC1782 error")+ 1;
udp_transmit(arptable[ARP_SERVER].
ipaddr, isocket,
ntohs(tr->udp.src),
len, (char *)&tp);
return (0);
}
}
if (p > e)
goto noak;
block = tp.u.ack.block = 0; /* this ensures, that */
/* the packet does not get */
/* processed as data! */
#else
continue;
#endif
}
else if (tr->opcode == ntohs(TFTP_DATA)) {
retry = MAX_TFTP_RETRIES;/*no more retries! */
len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;
if (len > packetsize) /* shouldn't happen */
continue; /* ignore it */
block = ntohs(tp.u.ack.block = tr->u.data.block); }
else /* neither TFTP_OACK nor TFTP_DATA */
break;
tp.opcode = htons(TFTP_ACK);
osocket = ntohs(tr->udp.src);
udp_transmit(arptable[ARP_SERVER].ipaddr, isocket,
osocket, TFTP_MIN_PACKET, (char *)&tp); /* ack */
if (block <= prevblock) /* retransmission or OACK */
continue; /* don't process */
prevblock = block;
if ((rc = fnc(tr->u.data.download,
block, len, len < packetsize)) >= 0)
return(rc);
if (len < packetsize) /* End of data */
return (1);
}
return (0);
}
/**************************************************************************
CONVERT_IPADDR - Convert IP address from net to machine order
**************************************************************************/
static void convert_ipaddr(d, s)
register char *d,*s;
{
d[3] = s[0];
d[2] = s[1];
d[1] = s[2];
d[0] = s[3];
}
/**************************************************************************
RFC951_SLEEP - sleep for expotentially longer times
**************************************************************************/
void rfc951_sleep(exp)
int exp;
{
static long seed = 0;
long q,z,tmo;
if (!seed) /* Initialize linear congruential generator */
seed = currticks() + *(long *)&arptable[ARP_CLIENT].node
+ ((short *)arptable[ARP_CLIENT].node)[2];
/* simplified version of the LCG given in Bruce Scheier's
"Applied Cryptography" */
q = seed/53668;
if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563l;
/* compute mask */
for (tmo = 63; tmo <= 60*18 && --exp > 0; tmo = 2*tmo+1);
/* sleep */
printf("<sleep>\r\n");
for (tmo = (tmo&seed)+currticks(); currticks() < tmo; )
/* if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1) */ ;
eth_reset();
return;
}
/**************************************************************************
TWIDDLE
**************************************************************************/
void twiddle()
{
static unsigned long lastticks = 0;
static int count=0;
static char tiddles[]="-\\|/";
unsigned long ticks;
if ((ticks = currticks()) < lastticks)
return;
lastticks = ticks+1;
putchar(tiddles[(count++)&3]);
putchar('\b');
}
/**************************************************************************
BOOTP - Get my IP address and load information
**************************************************************************/
static int bootp()
{
int retry;
struct bootp_t bp;
unsigned long starttime;
#ifdef T509HACK
int flag;
flag = 1;
#endif
bzero(&bp, sizeof(struct bootp_t));
bp.bp_op = BOOTP_REQUEST;
bp.bp_htype = 1;
bp.bp_hlen = ETHER_ADDR_SIZE;
bp.bp_xid = starttime = currticks();
bcopy(arptable[ARP_CLIENT].node, bp.bp_hwaddr, ETHER_ADDR_SIZE);
bcopy(rfc1533_cookie, bp.bp_vend, 5); /* request RFC-style options */
for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
udp_transmit(IP_BROADCAST, 0, BOOTP_SERVER,
sizeof(struct bootp_t), (char *)&bp);
#ifdef T509HACK
if (flag) {
flag--;
} else {
if (await_reply(AWAIT_BOOTP, 0, NULL))
return(1);
if (ip_abort) /* hohmuth */
return 0;
rfc951_sleep(++retry);
}
#else
if (await_reply(AWAIT_BOOTP, 0, NULL))
return(1);
if (ip_abort) /* hohmuth */
return 0;
rfc951_sleep(++retry);
#endif
bp.bp_secs = htons((currticks()-starttime)/20);
}
return(0);
}
/**************************************************************************
DEFAULT_NETMASK - Set a default netmask for IP address
**************************************************************************/
static void default_netmask()
{
int net = arptable[ARP_CLIENT].ipaddr >> 24;
if (net <= 127)
netmask = htonl(0xff000000);
else if (net < 192)
netmask = htonl(0xffff0000);
else
netmask = htonl(0xffffff00);
}
/**************************************************************************
DECODE_RFC1533 - Decodes RFC1533 header
**************************************************************************/
static int decode_rfc1533(p, block, len, eof)
register unsigned char *p;
int block, len, eof;
{
static unsigned char *extdata = NULL, *extend = NULL;
unsigned char *extpath = NULL;
unsigned char *end, *q;
if (block == 0) {
#ifdef IMAGE_MENU
bzero(imagelist, sizeof(imagelist));
menudefault = useimagemenu = 0;
menutmo = -1;
#endif
#ifdef MOTD
bzero(motd, sizeof(motd));
#endif
end_of_rfc1533 = NULL;
vendorext_isvalid = 0;
if (bcmp(p, rfc1533_cookie, 4))
return(0); /* no RFC 1533 header found */
p += 4;
end = p + len; }
else {
if (block == 1) {
if (bcmp(p, rfc1533_cookie, 4))
return(0); /* no RFC 1533 header found */
p += 4;
len -= 4; }
if (extend + len <= (unsigned char *)(&bootp_data+1)) {
bcopy(p, extend, len);
extend += len;
} else {
printf("Overflow in vendor data buffer! Aborting...\r\n");
*extdata = RFC1533_END;
return(0);
}
p = extdata; end = extend;
}
if (eof) {
while(p < end) {
unsigned char c = *p;
if (c == RFC1533_PAD) {p++; continue;}
else if (c == RFC1533_END) {
end_of_rfc1533 = end = p; continue; }
else if (c == RFC1533_NETMASK) {bcopy(p+2,&netmask,4);}
#ifdef NFS_BOOT
else if (c == RFC1533_HOSTNAME) {
if (TAG_LEN(p) < (MNAMELEN&~3)-1) {
bcopy(p+2,&nfsdiskless.my_hostnam,TAG_LEN(p));
nfsdiskless.my_hostnam[TAG_LEN(p)] = '\000';
hostnamelen = (TAG_LEN(p)+3)&~3;
}
}
#endif
else if (c == RFC1533_GATEWAY) {
/* This is a little simplistic, but it will
usually be sufficient; look into the gate-
way list, only if there has been no BOOTP
gateway. Take only the first entry */
if (TAG_LEN(p) >= 4 &&
arptable[ARP_GATEWAY].ipaddr == 0)
convert_ipaddr((char *)&arptable[ARP_GATEWAY].ipaddr,
p+2);
}
else if (c == RFC1533_EXTENSIONPATH)
extpath = p;
else if (c == RFC1533_VENDOR_MAGIC &&
TAG_LEN(p) >= 6 &&
!bcmp(p+2,vendorext_magic,4) &&
p[6] == RFC1533_VENDOR_MAJOR)
vendorext_isvalid++;
#ifdef IMAGE_MENU
else if (c == RFC1533_VENDOR_MNUOPTS) {
parse_menuopts(p+2, TAG_LEN(p));
}
else if (c >= RFC1533_VENDOR_IMG &&
c<RFC1533_VENDOR_IMG+RFC1533_VENDOR_NUMOFIMG){
imagelist[c - RFC1533_VENDOR_IMG] = p;
useimagemenu++;
}
#endif
#ifdef MOTD
else if (c >= RFC1533_VENDOR_MOTD &&
c < RFC1533_VENDOR_MOTD +
RFC1533_VENDOR_NUMOFMOTD)
motd[c - RFC1533_VENDOR_MOTD] = p;
#endif
else {
/* printf("Unknown RFC1533-tag ");
for(q=p;q<p+2+TAG_LEN(p);q++)
printf("%x ",*q);
printf("\n\r"); */ }
p += TAG_LEN(p) + 2;
}
extdata = extend = end;
if (block == 0 && extpath != NULL) {
char fname[64];
bcopy(extpath+2,fname,TAG_LEN(extpath));
fname[(int)TAG_LEN(extpath)] = '\000';
printf("Loading BOOTP-extension file: %s\r\n",fname);
tftp(fname,decode_rfc1533);
}
}
return(-1); /* proceed with next block */
}

15
netboot/ip.h Normal file
View file

@ -0,0 +1,15 @@
int ip_init(void);
int tftp(char *name, int (*fnc)(unsigned char *, int, int, int));
extern int ip_abort;
extern int udp_transmit (unsigned long destip, unsigned int srcsock,
unsigned int destsock, int len, char *buf);
extern int await_reply (int type, int ival, char *ptr);
extern unsigned short ipchksum (unsigned short *, int len);
extern void rfc951_sleep (int);
extern void twiddle (void);

426
netboot/lance.c Normal file
View file

@ -0,0 +1,426 @@
/**************************************************************************
Etherboot - BOOTP/TFTP Bootstrap Program
LANCE NIC driver for Etherboot
Large portions borrowed from the Linux LANCE driver by Donald Becker
Ken Yap, July 1997
***************************************************************************/
#ifdef INCLUDE_NE2100
/* to get some global routines like printf */
#include "netboot.h"
/* to get the interface to the body of the program */
#include "nic.h"
/* Offsets from base I/O address */
#define LANCE_DATA 0x10
#define LANCE_ADDR 0x12
#define LANCE_RESET 0x14
#define LANCE_BUS_IF 0x16
#define LANCE_TOTAL_SIZE 0x18
struct lance_init_block
{
unsigned short mode;
unsigned char phys_addr[6];
unsigned long filter[2];
Address rx_ring;
Address tx_ring;
};
struct lance_rx_head
{
union {
Address base;
char addr[4];
} u;
short buf_length; /* 2s complement */
short msg_length;
};
struct lance_tx_head
{
union {
Address base;
char addr[4];
} u;
short buf_length; /* 2s complement */
short misc;
};
struct lance_interface
{
struct lance_init_block init_block;
struct lance_rx_head rx_ring;
struct lance_tx_head tx_ring;
unsigned char rbuf[ETH_MAX_PACKET];
unsigned char tbuf[ETH_MAX_PACKET];
};
#define LANCE_MUST_PAD 0x00000001
#define LANCE_ENABLE_AUTOSELECT 0x00000002
#define LANCE_MUST_REINIT_RING 0x00000004
#define LANCE_MUST_UNRESET 0x00000008
#define LANCE_HAS_MISSED_FRAME 0x00000010
/* A mapping from the chip ID number to the part number and features.
These are from the datasheets -- in real life the '970 version
reportedly has the same ID as the '965. */
static struct lance_chip_type
{
int id_number;
char *name;
int flags;
} chip_table[] = {
{0x0000, "LANCE 7990", /* Ancient lance chip. */
LANCE_MUST_PAD + LANCE_MUST_UNRESET},
{0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
{0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
{0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
/* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so just call
it the PCnet32. */
{0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
{0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
{0x0, "PCnet (unknown)",
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
};
/* Define a macro for converting program addresses to real addresses */
/* Linux already defines it in asm/io.h */
#ifdef NETBOOT16
#define virt_to_bus(x) (((Address)x)+RELOC)
#endif /* NETBOOT16 */
static int chip_version;
static unsigned short ioaddr;
static int dma;
static struct lance_interface *lp;
/* additional 8 bytes for 8-byte alignment space */
static char lance[sizeof(struct lance_interface)+8];
#if defined(INCLUDE_NE2100)
#define lance_probe ne2100_probe
#endif
/* DMA defines and helper routines */
/* DMA controller registers */
#define DMA1_CMD_REG 0x08 /* command register (w) */
#define DMA1_STAT_REG 0x08 /* status register (r) */
#define DMA1_REQ_REG 0x09 /* request register (w) */
#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
#define DMA1_MODE_REG 0x0B /* mode register (w) */
#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
#define DMA2_CMD_REG 0xD0 /* command register (w) */
#define DMA2_STAT_REG 0xD0 /* status register (r) */
#define DMA2_REQ_REG 0xD2 /* request register (w) */
#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
#define DMA2_MODE_REG 0xD6 /* mode register (w) */
#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
/* enable/disable a specific DMA channel */
static void enable_dma(unsigned int dmanr)
{
if (dmanr <= 3)
outb_p(DMA1_MASK_REG, dmanr);
else
outb_p(DMA2_MASK_REG, dmanr & 3);
}
static void disable_dma(unsigned int dmanr)
{
if (dmanr <= 3)
outb_p(DMA1_MASK_REG, dmanr | 4);
else
outb_p(DMA2_MASK_REG, (dmanr & 3) | 4);
}
/* set mode (above) for a specific DMA channel */
static void set_dma_mode(unsigned int dmanr, char mode)
{
if (dmanr <= 3)
outb_p(DMA1_MODE_REG, mode | dmanr);
else
outb_p(DMA2_MODE_REG, mode | (dmanr&3));
}
/**************************************************************************
RESET - Reset adapter
***************************************************************************/
static void lance_reset(struct nic *nic)
{
int i;
Address l;
/* Reset the LANCE */
(void)inw(ioaddr+LANCE_RESET);
/* Un-Reset the LANCE, needed only for the NE2100 */
if (chip_table[chip_version].flags & LANCE_MUST_UNRESET)
outw(ioaddr+LANCE_RESET, 0);
if (chip_table[chip_version].flags & LANCE_ENABLE_AUTOSELECT)
{
/* This is 79C960 specific; Turn on auto-select of media
(AUI, BNC). */
outw(ioaddr+LANCE_ADDR, 0x2);
outw(ioaddr+LANCE_BUS_IF, 0x2);
}
/* Re-initialise the LANCE, and start it when done. */
/* Set station address */
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
lp->init_block.phys_addr[i] = nic->node_addr[i];
/* Preset the receive ring header */
lp->rx_ring.buf_length = -ETH_MAX_PACKET;
/* OWN */
lp->rx_ring.u.base = virt_to_bus(lp->rbuf) & 0xffffff;
/* we set the top byte as the very last thing */
lp->rx_ring.u.addr[3] = 0x80;
lp->init_block.mode = 0x0; /* enable Rx and Tx */
l = (Address)virt_to_bus(&lp->init_block);
outw(ioaddr+LANCE_ADDR, 0x1);
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, (short)l);
outw(ioaddr+LANCE_ADDR, 0x2);
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, (short)(l >> 16));
outw(ioaddr+LANCE_ADDR, 0x4);
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, 0x915);
outw(ioaddr+LANCE_ADDR, 0x0);
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, 0x4); /* stop */
outw(ioaddr+LANCE_DATA, 0x1); /* init */
for (i = 100; i > 0; --i)
if (inw(ioaddr+LANCE_DATA) & 0x100)
break;
/* Apparently clearing the InitDone bit here triggers a bug
in the '974. (Mark Stockton) */
outw(ioaddr+LANCE_DATA, 0x2); /* start */
}
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
static int lance_poll(struct nic *nic)
{
int status;
status = lp->rx_ring.u.base >> 24;
if (status & 0x80)
return (0);
#ifdef DEBUG
printf("LANCE packet received rx_ring.u.base %X mcnt %x csr0 %x\r\n",
lp->rx_ring.u.base, lp->rx_ring.msg_length,
inw(ioaddr+LANCE_DATA));
#endif
if (status == 0x3)
bcopy(lp->rbuf, nic->packet, nic->packetlen = lp->rx_ring.msg_length);
/* Andrew Boyd of QNX reports that some revs of the 79C765
clear the buffer length */
lp->rx_ring.buf_length = -ETH_MAX_PACKET;
lp->rx_ring.u.addr[3] |= 0x80; /* prime for next receive */
outw(ioaddr+LANCE_ADDR, 0x0);
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, 0x500); /* clear receive + InitDone */
return (status == 0x3);
}
/**************************************************************************
TRANSMIT - Transmit a frame
***************************************************************************/
static void lance_transmit(
struct nic *nic,
char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
{
unsigned long time;
/* copy the packet to ring buffer */
bcopy(d, lp->tbuf, ETHER_ADDR_SIZE); /* dst */
bcopy(nic->node_addr, &lp->tbuf[ETHER_ADDR_SIZE], ETHER_ADDR_SIZE); /* src */
lp->tbuf[ETHER_ADDR_SIZE+ETHER_ADDR_SIZE] = t >> 8; /* type */
lp->tbuf[ETHER_ADDR_SIZE+ETHER_ADDR_SIZE+1] = t; /* type */
bcopy(p, &lp->tbuf[ETHER_HDR_SIZE], s);
s += ETHER_HDR_SIZE;
if (chip_table[chip_version].flags & LANCE_MUST_PAD)
while (s < ETH_MIN_PACKET) /* pad to min length */
lp->tbuf[s++] = 0;
lp->tx_ring.buf_length = -s;
lp->tx_ring.misc = 0x0;
/* OWN, STP, ENP */
lp->tx_ring.u.base = virt_to_bus(lp->tbuf) & 0xffffff;
/* we set the top byte as the very last thing */
lp->tx_ring.u.addr[3] = 0x83;
/* Trigger an immediate send poll */
outw(ioaddr+LANCE_ADDR, 0x0);
outw(ioaddr+LANCE_DATA, 0x48);
/* wait for transmit complete */
time = currticks() + 18; /* wait one second */
while (currticks() < time && (lp->tx_ring.u.base & 0x80000000) != 0)
;
if ((lp->tx_ring.u.base & 0x80000000) != 0)
printf("LANCE timed out on transmit\r\n");
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, 0x200); /* clear transmit + InitDone */
#ifdef DEBUG
printf("tx_ring.u.base %X tx_ring.buf_length %x tx_ring.misc %x csr0 %x\r\n",
lp->tx_ring.u.base, lp->tx_ring.buf_length, lp->tx_ring.misc,
inw(ioaddr+LANCE_DATA));
#endif
}
static void lance_disable(struct nic *nic)
{
disable_dma(dma);
}
static int lance_probe1(struct nic *nic)
{
int reset_val, lance_version, i;
Address l;
short dma_channels;
static char dmas[] = { 5, 6, 7, 3 };
reset_val = inw(ioaddr+LANCE_RESET);
outw(ioaddr+LANCE_ADDR, 0x0); /* Switch to window 0 */
if (inw(ioaddr+LANCE_DATA) != 0x4)
return (-1);
outw(ioaddr+LANCE_ADDR, 88); /* Get the version of the chip */
if (inw(ioaddr+LANCE_ADDR) != 88)
lance_version = 0;
else
{
chip_version = inw(ioaddr+LANCE_DATA);
outw(ioaddr+LANCE_ADDR, 89);
chip_version |= inw(ioaddr+LANCE_DATA) << 16;
if ((chip_version & 0xfff) != 0x3)
return (-1);
chip_version = (chip_version >> 12) & 0xffff;
for (lance_version = 1; chip_table[lance_version].id_number != 0; ++lance_version)
if (chip_table[lance_version].id_number == chip_version)
break;
}
/* make sure data structure is 8-byte aligned */
l = ((Address)lance + 7) & ~7;
lp = (struct lance_interface *)l;
lp->init_block.mode = 0x3; /* disable Rx and Tx */
lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
/* top bits are zero, we have only one buffer each for Rx and Tx */
lp->init_block.rx_ring = virt_to_bus(&lp->rx_ring) & 0xffffff;
lp->init_block.tx_ring = virt_to_bus(&lp->tx_ring) & 0xffffff;
l = virt_to_bus(&lp->init_block);
outw(ioaddr+LANCE_ADDR, 0x1);
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, (unsigned short)l);
outw(ioaddr+LANCE_ADDR, 0x2);
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, (unsigned short)(l >> 16));
outw(ioaddr+LANCE_ADDR, 0x4);
(void)inw(ioaddr+LANCE_ADDR);
outw(ioaddr+LANCE_DATA, 0x915);
outw(ioaddr+LANCE_ADDR, 0x0);
(void)inw(ioaddr+LANCE_ADDR);
/* now probe for DMA channel */
dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0xf) |
(inb(DMA2_STAT_REG) & 0xf0);
/* need to fix when PCI provides DMA info */
for (i = 0; i < (sizeof(dmas)/sizeof(dmas[0])); ++i)
{
int j;
dma = dmas[i];
/* Don't enable a permanently busy DMA channel,
or the machine will hang */
if (dma_channels & (1 << dma))
continue;
outw(ioaddr+LANCE_DATA, 0x7f04); /* clear memory error bits */
set_dma_mode(dma, DMA_MODE_CASCADE);
enable_dma(dma);
outw(ioaddr+LANCE_DATA, 0x1); /* init */
for (j = 100; j > 0; --j)
if (inw(ioaddr+LANCE_DATA) & 0x900)
break;
if (inw(ioaddr+LANCE_DATA) & 0x100)
break;
else
disable_dma(dma);
}
if (i >= (sizeof(dmas)/sizeof(dmas[0])))
dma = 0;
printf("\r\n%s base 0x%x, DMA %d, addr ",
chip_table[lance_version].name, ioaddr, dma);
/* Get station address */
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
{
printf("%b", nic->node_addr[i] = inb(ioaddr+i));
if (i < ETHER_ADDR_SIZE -1)
printf(":");
}
printf("\r\n");
return (lance_version);
}
/**************************************************************************
PROBE - Look for an adapter, this routine's visible to the outside
***************************************************************************/
struct nic *lance_probe(struct nic *nic, unsigned short *probe_addrs)
{
unsigned short *p;
static unsigned short io_addrs[] = { 0x300, 0x320, 0x340, 0x360, 0 };
/* if probe_addrs is 0, then routine can use a hardwired default */
if (probe_addrs == 0)
probe_addrs = io_addrs;
for (p = probe_addrs; (ioaddr = *p) != 0; ++p)
{
char offset15, offset14 = inb(ioaddr + 14);
if ((offset14 == 0x52 || offset14 == 0x57) &&
((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44))
if (lance_probe1(nic) >= 0)
break;
}
/* if board found */
if (ioaddr != 0)
{
/* point to NIC specific routines */
lance_reset(nic);
nic->reset = lance_reset;
nic->poll = lance_poll;
nic->transmit = lance_transmit;
nic->disable = lance_disable;
return nic;
}
/* else */
{
return 0;
}
}
#endif /* INCLUDE_NE2100 */

471
netboot/netboot.h Normal file
View file

@ -0,0 +1,471 @@
/**************************************************************************
NETBOOT - BOOTP/TFTP Bootstrap Program
Author: Martin Renters
Date: Dec/93
**************************************************************************/
#define NETBOOT32
#include "../stage2/shared.h"
#include "byteorder.h"
#include "io.h"
typedef unsigned long Address;
extern int _pending_key;
extern inline int getchar(void);
extern inline int getchar(void) {
int foo;
if (_pending_key == -1)
return getkey();
foo = _pending_key;
_pending_key = -1;
return foo;
}
extern inline int iskey(void);
extern inline int iskey(void) {
return _pending_key != -1 ? 1 : ((_pending_key = checkkey()) != -1);
}
#if 0 /*Edmund*/
#define bcmp __builtin_memcmp
#define memcpy(d,s,sz) bcopy((s),(d),(sz))
#else
#define bcopy(src, dest, n) memcpy(dest, src, n)
#define bzero(s, n) memset(s, 0, n)
#define bcmp(s1, s2, n) memcmp(s1, s2, n)
#endif
/* ANSI prototyping macro */
#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
#endif
#define ESC 0x1B
#ifndef DEFAULT_BOOTFILE
#define DEFAULT_BOOTFILE "/kernel"
#endif
#ifndef MAX_TFTP_RETRIES
#define MAX_TFTP_RETRIES 20
#endif
#ifndef MAX_BOOTP_RETRIES
#define MAX_BOOTP_RETRIES 20
#endif
#ifndef MAX_BOOTP_EXTLEN
#define MAX_BOOTP_EXTLEN 1024
#endif
#ifndef MAX_ARP_RETRIES
#define MAX_ARP_RETRIES 20
#endif
#ifndef MAX_RPC_RETRIES
#define MAX_RPC_RETRIES 20
#endif
#ifndef TIMEOUT /* Inter-packet retry in ticks 18/sec */
#define TIMEOUT 180
#endif
#ifndef NULL
#define NULL ((void *)0)
#endif
#define TRUE 1
#define FALSE 0
#define ETHER_ADDR_SIZE 6 /* Size of Ethernet address */
#define ETHER_HDR_SIZE 14 /* Size of ethernet header */
#define ETH_MIN_PACKET 64
#define ETH_MAX_PACKET 1518
#define VENDOR_NONE 0
#define VENDOR_WD 1
#define VENDOR_NOVELL 2
#define VENDOR_3COM 3
#define VENDOR_3C509 4
#define VENDOR_CS89x0 5
#define FLAG_PIO 0x01
#define FLAG_16BIT 0x02
#define FLAG_790 0x04
#define ARP_CLIENT 0
#define ARP_SERVER 1
#define ARP_GATEWAY 2
#define ARP_ROOTSERVER 3
#define ARP_SWAPSERVER 4
#define MAX_ARP ARP_SWAPSERVER+1
#define IP 0x0800
#define ARP 0x0806
#define BOOTP_SERVER 67
#define BOOTP_CLIENT 68
#define TFTP 69
#define SUNRPC 111
#define RPC_SOCKET 620 /* Arbitrary */
#define IP_UDP 17
#define IP_BROADCAST 0xFFFFFFFF
#define ARP_REQUEST 1
#define ARP_REPLY 2
#define BOOTP_REQUEST 1
#define BOOTP_REPLY 2
#define TAG_LEN(p) (*((p)+1))
#define RFC1533_COOKIE 99, 130, 83, 99
#define RFC1533_PAD 0
#define RFC1533_NETMASK 1
#define RFC1533_TIMEOFFSET 2
#define RFC1533_GATEWAY 3
#define RFC1533_TIMESERVER 4
#define RFC1533_IEN116NS 5
#define RFC1533_DNS 6
#define RFC1533_LOGSERVER 7
#define RFC1533_COOKIESERVER 8
#define RFC1533_LPRSERVER 9
#define RFC1533_IMPRESSSERVER 10
#define RFC1533_RESOURCESERVER 11
#define RFC1533_HOSTNAME 12
#define RFC1533_BOOTFILESIZE 13
#define RFC1533_MERITDUMPFILE 14
#define RFC1533_DOMAINNAME 15
#define RFC1533_SWAPSERVER 16
#define RFC1533_ROOTPATH 17
#define RFC1533_EXTENSIONPATH 18
#define RFC1533_IPFORWARDING 19
#define RFC1533_IPSOURCEROUTING 20
#define RFC1533_IPPOLICYFILTER 21
#define RFC1533_IPMAXREASSEMBLY 22
#define RFC1533_IPTTL 23
#define RFC1533_IPMTU 24
#define RFC1533_IPMTUPLATEAU 25
#define RFC1533_INTMTU 26
#define RFC1533_INTLOCALSUBNETS 27
#define RFC1533_INTBROADCAST 28
#define RFC1533_INTICMPDISCOVER 29
#define RFC1533_INTICMPRESPOND 30
#define RFC1533_INTROUTEDISCOVER 31
#define RFC1533_INTROUTESOLICIT 32
#define RFC1533_INTSTATICROUTES 33
#define RFC1533_LLTRAILERENCAP 34
#define RFC1533_LLARPCACHETMO 35
#define RFC1533_LLETHERNETENCAP 36
#define RFC1533_TCPTTL 37
#define RFC1533_TCPKEEPALIVETMO 38
#define RFC1533_TCPKEEPALIVEGB 39
#define RFC1533_NISDOMAIN 40
#define RFC1533_NISSERVER 41
#define RFC1533_NTPSERVER 42
#define RFC1533_VENDOR 43
#define RFC1533_NBNS 44
#define RFC1533_NBDD 45
#define RFC1533_NBNT 46
#define RFC1533_NBSCOPE 47
#define RFC1533_XFS 48
#define RFC1533_XDM 49
#define RFC1533_VENDOR_MAJOR 0
#define RFC1533_VENDOR_MINOR 0
#define RFC1533_VENDOR_MAGIC 128
#define RFC1533_VENDOR_ADDPARM 129
#define RFC1533_VENDOR_MNUOPTS 160
#define RFC1533_VENDOR_SELECTION 176
#define RFC1533_VENDOR_MOTD 184
#define RFC1533_VENDOR_NUMOFMOTD 8
#define RFC1533_VENDOR_IMG 192
#define RFC1533_VENDOR_NUMOFIMG 16
#define RFC1533_END 255
#define BOOTP_VENDOR_LEN 64
#define TFTP_DEFAULTSIZE_PACKET 512
#define TFTP_MAX_PACKET 1432 /* 512 */
#define TFTP_RRQ 1
#define TFTP_WRQ 2
#define TFTP_DATA 3
#define TFTP_ACK 4
#define TFTP_ERROR 5
#define TFTP_OACK 6
#define TFTP_CODE_EOF 1
#define TFTP_CODE_MORE 2
#define TFTP_CODE_ERROR 3
#define TFTP_CODE_BOOT 4
#define TFTP_CODE_CFG 5
#define PROG_PORTMAP 100000
#define PROG_NFS 100003
#define PROG_MOUNT 100005
#define MSG_CALL 0
#define MSG_REPLY 1
#define PORTMAP_LOOKUP 3
#define MOUNT_ADDENTRY 1
#define MOUNT_UMNTALL 4
#define NFS_LOOKUP 4
#define NFS_READ 6
#define NFS_READ_SIZE 1024
#define AWAIT_ARP 0
#define AWAIT_BOOTP 1
#define AWAIT_TFTP 2
#define AWAIT_RPC 3
struct arptable_t {
unsigned long ipaddr;
unsigned char node[6];
};
struct arprequest {
unsigned short hwtype;
unsigned short protocol;
char hwlen;
char protolen;
unsigned short opcode;
char shwaddr[6];
char sipaddr[4];
char thwaddr[6];
char tipaddr[4];
};
struct iphdr {
char verhdrlen;
char service;
unsigned short len;
unsigned short ident;
unsigned short frags;
char ttl;
char protocol;
unsigned short chksum;
char src[4];
char dest[4];
};
struct udphdr {
unsigned short src;
unsigned short dest;
unsigned short len;
unsigned short chksum;
};
struct bootp_t {
struct iphdr ip;
struct udphdr udp;
char bp_op;
char bp_htype;
char bp_hlen;
char bp_hops;
unsigned long bp_xid;
unsigned short bp_secs;
unsigned short unused;
char bp_ciaddr[4];
char bp_yiaddr[4];
char bp_siaddr[4];
char bp_giaddr[4];
char bp_hwaddr[16];
char bp_sname[64];
char bp_file[128];
char bp_vend[BOOTP_VENDOR_LEN];
};
struct bootpd_t {
struct bootp_t bootp_reply;
unsigned char bootp_extension[MAX_BOOTP_EXTLEN];
};
struct tftp_t {
struct iphdr ip;
struct udphdr udp;
unsigned short opcode;
union {
char rrq[TFTP_DEFAULTSIZE_PACKET];
struct {
unsigned short block;
char download[TFTP_MAX_PACKET];
} data;
struct {
unsigned short block;
} ack;
struct {
unsigned short errcode;
char errmsg[TFTP_DEFAULTSIZE_PACKET];
} err;
struct {
char data[TFTP_DEFAULTSIZE_PACKET+2];
} oack;
} u;
};
struct rpc_t {
struct iphdr ip;
struct udphdr udp;
union {
char data[1400];
struct {
long id;
long type;
long rstatus;
long verifier;
long v2;
long astatus;
long data[1];
} reply;
} u;
};
#define TFTP_MIN_PACKET (sizeof(struct iphdr) + sizeof(struct udphdr) + 4)
/***************************************************************************
RPC Functions
***************************************************************************/
#define PUTLONG(val) {\
register int lval = val; \
*(rpcptr++) = ((lval) >> 24); \
*(rpcptr++) = ((lval) >> 16); \
*(rpcptr++) = ((lval) >> 8); \
*(rpcptr++) = (lval); \
rpclen+=4; }
#if 0 /* XXX */
/***************************************************************************
External prototypes
***************************************************************************/
/* main.c */
extern void load P((void));
extern int load_linux P((int root_mount_port,int swap_mount_port,
int root_nfs_port,char *kernel_handle));
extern int linux_tftp P((unsigned int block,unsigned char *data,int len));
extern int tftpkernel P((unsigned char *, int, int, int));
extern int tftp P((char *name, int (*)(unsigned char *, int, int, int)));
extern int bootp P((void));
extern int udp_transmit P((unsigned long destip, unsigned int srcsock,
unsigned int destsock, int len, char *buf));
extern int await_reply P((int type, int ival, char *ptr));
extern void default_netmask P((void));
extern int decode_rfc1533 P((unsigned char *, int, int, int));
extern unsigned short ipchksum P((unsigned short *, int len));
extern void convert_ipaddr P((char *, char *));
extern void rfc951_sleep P((int));
/* bootmenu.c */
extern int execute P((char *string));
extern void bootmenu P((void));
extern void show_motd P((void));
extern void parse_menuopts P((char *,int));
extern int getoptvalue P((char **, int *, int *));
extern void selectImage P((char **, char *, struct arptable_t *));
/* linuxloader.c */
extern char *linux_add_cmdline P((char *string));
/* rpc.c */
extern int rpclookup P((int addr, int prog, int ver));
extern int nfs_mount P((int server, int port, char *path, char *fh));
extern int nfs_umountall P((int server, int port));
extern int nfs_lookup P((int server, int port, char *fh, char *path, char *file_fh));
extern int nfs_read P((int server, int port, char *fh, int offset, int len, char *buffer));
extern void rpc_err P((struct rpc_t *rpc));
extern void nfs_err P((int err));
/* misc.c */
#if 0 /*Edmund*/
extern void bcopy P((void *src, void *dst, int cnt));
extern void bzero P((void *dst, int cnt));
extern int bcmp P((void *src, void *dst, int cnt));
#endif
extern int strcasecmp P((char *a, char *b));
extern char *substr P((char *a, char *b));
extern int getdec P((char **));
extern void twiddle P((void));
extern void printf(); /* old style to avoid varargs */
extern char *sprintf();
extern int setip P((char *p, unsigned long *i));
extern void gateA20 P((void));
/* start*.S */
extern int getchar P((void));
extern void putchar P((int));
extern int iskey P((void));
extern int getshift P((void));
extern unsigned short memsize P((void));
extern void disk_init P((void));
extern short disk_read P((int drv,int c,int h,int s,char *buf));
extern void start_linux P((void));
extern void xstart P((unsigned long, unsigned long, unsigned long));
extern long currticks P((void));
extern int setjmp P((void *jmpbuf));
extern void longjmp P((void *jmpbuf, int where));
extern void exit P((int status));
/* ansiesc.c */
extern void ansi_reset P((void));
extern void enable_cursor P((int));
/* md5.c */
extern void md5_put P((unsigned int ch));
extern void md5_done P((unsigned char *buf));
/* floppy.c */
extern int bootdisk P((int dev,int part));
#endif
/***************************************************************************
External variables
***************************************************************************/
/* main.c */
extern char *kernel;
extern char kernel_buf[];
extern struct nfs_diskless nfsdiskless;
extern int hostnamelen;
extern unsigned long netmask;
extern int jmp_bootmenu[10];
extern char kernel_buf[128];
extern struct bootpd_t bootp_data;
extern struct arptable_t arptable[MAX_ARP];
extern char *imagelist[RFC1533_VENDOR_NUMOFIMG];
extern char *motd[RFC1533_VENDOR_NUMOFMOTD];
extern int menutmo,menudefault;
extern unsigned char *end_of_rfc1533;
/* bootmenu.c */
/* linuxloader.c */
/* rpc.c */
extern int rpc_id;
/* created by linker */
extern char _edata[], _end[];
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

195
netboot/netdevice.h Normal file
View file

@ -0,0 +1,195 @@
/*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* Definitions for the Interfaces handler.
*
* Version: @(#)dev.h 1.0.10 08/12/93
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Corey Minyard <wf-rch!minyard@relay.EU.net>
* Donald J. Becker, <becker@super.org>
* Alan Cox, <A.Cox@swansea.ac.uk>
* Bjorn Ekwall. <bj0rn@blox.se>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Moved to /usr/include/linux for NET3
*/
/* for future expansion when we will have different priorities. */
#define DEV_NUMBUFFS 3
#define MAX_ADDR_LEN 7
#ifndef CONFIG_AX25
#ifndef CONFIG_TR
#ifndef CONFIG_NET_IPIP
#define MAX_HEADER 32 /* We really need about 18 worst case .. so 32 is aligned */
#else
#define MAX_HEADER 80 /* We need to allow for having tunnel headers */
#endif /* IPIP */
#else
#define MAX_HEADER 48 /* Token Ring header needs 40 bytes ... 48 is aligned */
#endif /* TR */
#else
#define MAX_HEADER 96 /* AX.25 + NetROM */
#endif /* AX25 */
#define IS_MYADDR 1 /* address is (one of) our own */
#define IS_LOOPBACK 2 /* address is for LOOPBACK */
#define IS_BROADCAST 3 /* address is a valid broadcast */
#define IS_INVBCAST 4 /* Wrong netmask bcast not for us (unused)*/
#define IS_MULTICAST 5 /* Multicast IP address */
/*
* The DEVICE structure.
* Actually, this whole structure is a big mistake. It mixes I/O
* data with strictly "high-level" data, and it has to know about
* almost every data structure used in the INET module.
*/
struct device
{
/*
* This is the first field of the "visible" part of this structure
* (i.e. as seen by users in the "Space.c" file). It is the name
* the interface.
*/
char *name;
/* I/O specific fields - FIXME: Merge these and struct ifmap into one */
unsigned long rmem_end; /* shmem "recv" end */
unsigned long rmem_start; /* shmem "recv" start */
unsigned long mem_end; /* shared mem end */
unsigned long mem_start; /* shared mem start */
unsigned long base_addr; /* device I/O address */
unsigned char irq; /* device IRQ number */
/* Low-level status flags. */
volatile unsigned char start, /* start an operation */
interrupt; /* interrupt arrived */
unsigned long tbusy; /* transmitter busy must be long for bitops */
struct device *next;
/* The device initialization function. Called only once. */
int (*init)(struct device *dev);
/* Some hardware also needs these fields, but they are not part of the
usual set specified in Space.c. */
unsigned char if_port; /* Selectable AUI, TP,..*/
unsigned char dma; /* DMA channel */
/* struct enet_statistics* (*get_stats)(struct device *dev); */
/*
* This marks the end of the "visible" part of the structure. All
* fields hereafter are internal to the system, and may change at
* will (read: may be cleaned up at will).
*/
/* These may be needed for future network-power-down code. */
unsigned long trans_start; /* Time (in jiffies) of last Tx */
unsigned long last_rx; /* Time of last Rx */
unsigned short flags; /* interface flags (a la BSD) */
unsigned short family; /* address family ID (AF_INET) */
unsigned short metric; /* routing metric (not used) */
unsigned short mtu; /* interface MTU value */
unsigned short type; /* interface hardware type */
unsigned short hard_header_len; /* hardware hdr length */
void *priv; /* pointer to private data */
/* Interface address info. */
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
unsigned char pad; /* make dev_addr aligned to 8 bytes */
unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */
unsigned char addr_len; /* hardware address length */
unsigned long pa_addr; /* protocol address */
unsigned long pa_brdaddr; /* protocol broadcast addr */
unsigned long pa_dstaddr; /* protocol P-P other side addr */
unsigned long pa_mask; /* protocol netmask */
unsigned short pa_alen; /* protocol address length */
#if 0
struct dev_mc_list *mc_list; /* Multicast mac addresses */
#endif
int mc_count; /* Number of installed mcasts */
#if 0
struct ip_mc_list *ip_mc_list; /* IP multicast filter chain */
#endif
unsigned int tx_queue_len; /* Max frames per queue allowed */
/* For load balancing driver pair support */
unsigned long pkt_queue; /* Packets queued */
#if 0
struct device *slave; /* Slave device */
struct net_alias_info *alias_info; /* main dev alias info */
struct net_alias *my_alias; /* alias devs */
/* Pointer to the interface buffers. */
struct sk_buff_head buffs[DEV_NUMBUFFS];
#endif
int (*change_mtu)(struct device *dev, int new_mtu);
};
#if 0
struct packet_type {
unsigned short type; /* This is really htons(ether_type). */
struct device * dev;
int (*func) (struct sk_buff *, struct device *,
struct packet_type *);
void *data;
struct packet_type *next;
};
/* Used by dev_rint */
#define IN_SKBUFF 1
extern int dev_lockct;
/*
* These two don't currently need to be interrupt-safe
* but they may do soon. Do it properly anyway.
*/
extern __inline__ void dev_lock_list(void)
{
unsigned long flags;
save_flags(flags);
cli();
dev_lockct++;
restore_flags(flags);
}
extern __inline__ void dev_unlock_list(void)
{
unsigned long flags;
save_flags(flags);
cli();
dev_lockct--;
restore_flags(flags);
}
/*
* This almost never occurs, isn't in performance critical paths
* and we can thus be relaxed about it
*/
extern __inline__ void dev_lock_wait(void)
{
while(dev_lockct)
schedule();
}
#endif /* _LINUX_DEV_H */

18
netboot/nic.h Normal file
View file

@ -0,0 +1,18 @@
/*
* Structure returned from eth_probe and passed to other driver
* functions.
*/
struct nic
{
void (*reset)P((struct nic *));
int (*poll)P((struct nic *));
void (*transmit)P((struct nic *, char *d,
unsigned int t, unsigned int s, char *p));
void (*disable)P((struct nic *));
char aui;
char *node_addr;
char *packet;
int packetlen;
void *priv_data; /* driver can hang private data here */
};

746
netboot/ns8390.c Normal file
View file

@ -0,0 +1,746 @@
/**************************************************************************
NETBOOT - BOOTP/TFTP Bootstrap Program
Author: Martin Renters
Date: May/94
This code is based heavily on David Greenman's if_ed.c driver
Copyright (C) 1993-1994, David Greenman, Martin Renters.
This software may be used, modified, copied, distributed, and sold, in
both source and binary form provided that the above copyright and these
terms are retained. Under no circumstances are the authors responsible for
the proper functioning of this software, nor do the authors assume any
responsibility for damages incurred with its use.
3c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94
SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/94
**************************************************************************/
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI) || defined(INCLUDE_WD) || defined(INCLUDE_T503)
#include "netboot.h"
#include "nic.h"
#include "ns8390.h"
static unsigned char eth_vendor, eth_flags, eth_laar;
static unsigned short eth_nic_base, eth_asic_base;
static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
static Address eth_bmem, eth_rmem;
#if defined(INCLUDE_WD)
#define eth_probe wd_probe
#else
#if defined(INCLUDE_T503)
#define eth_probe t503_probe
#else
#if defined(INCLUDE_NE)
#define eth_probe ne_probe
#else
#if defined(INCLUDE_NEPCI)
#define eth_probe nepci_probe
#else
Error you must define one of the above
#endif
#endif
#endif
#endif
static void net_bcopy (char *s, char *d, int l)
{
while (l--)
*d++ = *s++;
}
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI)
/**************************************************************************
ETH_PIO_READ - Read a frame via Programmed I/O
**************************************************************************/
static void eth_pio_read(src, dst, cnt)
unsigned int src;
unsigned char *dst;
unsigned int cnt;
{
if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }
outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD2 |
D8390_COMMAND_STA);
outb(eth_nic_base + D8390_P0_RBCR0, cnt);
outb(eth_nic_base + D8390_P0_RBCR1, cnt>>8);
outb(eth_nic_base + D8390_P0_RSAR0, src);
outb(eth_nic_base + D8390_P0_RSAR1, src>>8);
outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD0 |
D8390_COMMAND_STA);
if (eth_flags & FLAG_16BIT) {
cnt >>= 1; /* number of words */
while (cnt--) {
*((unsigned short *)dst) = inw(eth_asic_base + NE_DATA);
dst += 2;
}
}
else {
while (cnt--)
*(dst++) = inb(eth_asic_base + NE_DATA);
}
}
/**************************************************************************
ETH_PIO_WRITE - Write a frame via Programmed I/O
**************************************************************************/
static void eth_pio_write(src, dst, cnt)
unsigned char *src;
unsigned int dst;
unsigned int cnt;
{
if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }
outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD2 |
D8390_COMMAND_STA);
outb(eth_nic_base + D8390_P0_ISR, D8390_ISR_RDC);
outb(eth_nic_base + D8390_P0_RBCR0, cnt);
outb(eth_nic_base + D8390_P0_RBCR1, cnt>>8);
outb(eth_nic_base + D8390_P0_RSAR0, dst);
outb(eth_nic_base + D8390_P0_RSAR1, dst>>8);
outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD1 |
D8390_COMMAND_STA);
if (eth_flags & FLAG_16BIT) {
cnt >>= 1; /* number of words */
while (cnt--) {
outw_p(eth_asic_base + NE_DATA, *((unsigned short *)src));
src += 2;
}
}
else {
while (cnt--)
outb_p(eth_asic_base + NE_DATA, *(src++));
}
while((inb_p(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)
!= D8390_ISR_RDC);
}
#else
/**************************************************************************
ETH_PIO_READ - Dummy routine when NE2000 not compiled in
**************************************************************************/
static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {}
#endif
/**************************************************************************
ETH_RESET - Reset adapter
**************************************************************************/
static void eth_reset(struct nic *nic)
{
int i;
if (eth_flags & FLAG_790)
outb(eth_nic_base+D8390_P0_COMMAND,
D8390_COMMAND_PS0 | D8390_COMMAND_STP);
else
outb(eth_nic_base+D8390_P0_COMMAND,
D8390_COMMAND_PS0 | D8390_COMMAND_RD2 |
D8390_COMMAND_STP);
if (eth_flags & FLAG_16BIT)
outb(eth_nic_base+D8390_P0_DCR, 0x49);
else
outb(eth_nic_base+D8390_P0_DCR, 0x48);
outb(eth_nic_base+D8390_P0_RBCR0, 0);
outb(eth_nic_base+D8390_P0_RBCR1, 0);
outb(eth_nic_base+D8390_P0_RCR, 0x20); /* monitor mode */
outb(eth_nic_base+D8390_P0_TCR, 2);
outb(eth_nic_base+D8390_P0_TPSR, eth_tx_start);
outb(eth_nic_base+D8390_P0_PSTART, eth_rx_start);
if (eth_flags & FLAG_790) outb(eth_nic_base + 0x09, 0);
outb(eth_nic_base+D8390_P0_PSTOP, eth_memsize);
outb(eth_nic_base+D8390_P0_BOUND, eth_memsize - 1);
outb(eth_nic_base+D8390_P0_ISR, 0xFF);
outb(eth_nic_base+D8390_P0_IMR, 0);
if (eth_flags & FLAG_790)
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1 |
D8390_COMMAND_STP);
else
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1 |
D8390_COMMAND_RD2 | D8390_COMMAND_STP);
for (i=0; i<ETHER_ADDR_SIZE; i++)
outb(eth_nic_base+D8390_P1_PAR0+i, nic->node_addr[i]);
for (i=0; i<ETHER_ADDR_SIZE; i++)
outb(eth_nic_base+D8390_P1_MAR0+i, 0xFF);
outb(eth_nic_base+D8390_P1_CURR, eth_rx_start);
if (eth_flags & FLAG_790)
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 |
D8390_COMMAND_STA);
else
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 |
D8390_COMMAND_RD2 | D8390_COMMAND_STA);
outb(eth_nic_base+D8390_P0_ISR, 0xFF);
outb(eth_nic_base+D8390_P0_TCR, 0);
outb(eth_nic_base+D8390_P0_RCR, 4); /* allow broadcast frames */
#ifdef INCLUDE_T503
if (eth_vendor == VENDOR_3COM) {
/*
* No way to tell whether or not we're supposed to use
* the 3Com's transceiver unless the user tells us.
* 'aui' should have some compile time default value
* which can be changed from the command menu.
*/
if (nic->aui)
outb(eth_asic_base + _3COM_CR, 0);
else
outb(eth_asic_base + _3COM_CR, _3COM_CR_XSEL);
}
#endif
}
/**************************************************************************
ETH_TRANSMIT - Transmit a frame
**************************************************************************/
static void eth_transmit(
struct nic *nic,
char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
{
int c; /* used in NETBOOT16 */
#ifdef INCLUDE_T503
if (eth_vendor == VENDOR_3COM) {
#ifdef NETBOOT32
net_bcopy(d, (void *)eth_bmem, ETHER_ADDR_SIZE); /* dst */
net_bcopy(nic->node_addr, (void *)eth_bmem+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE); /* src */
*((char *)eth_bmem+12) = t>>8; /* type */
*((char *)eth_bmem+13) = t;
net_bcopy(p, (void *)eth_bmem+ETHER_HDR_SIZE, s);
s += ETHER_HDR_SIZE;
while (s < ETH_MIN_PACKET) *((char *)eth_bmem+(s++)) = 0;
#endif
#ifdef NETBOOT16
bcopyf(d, eth_bmem, ETHER_ADDR_SIZE);
bcopyf(nic->node_addr, eth_bmem+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE);
c = t >> 8;
bcopyf(&c, eth_bmem+12, 1);
c = t;
bcopyf(&c, eth_bmem+13, 1);
bcopyf(p, (Address)(eth_bmem+ETHER_HDR_SIZE), s);
s += ETHER_HDR_SIZE;
if (s < ETH_MIN_PACKET)
bzerof(eth_bmem+s, ETH_MIN_PACKET-s), s = ETH_MIN_PACKET;
#endif
}
#endif
#ifdef INCLUDE_WD
if (eth_vendor == VENDOR_WD) { /* Memory interface */
if (eth_flags & FLAG_16BIT) {
outb(eth_asic_base + WD_LAAR, eth_laar | WD_LAAR_M16EN);
inb(0x84);
}
if (eth_flags & FLAG_790) {
outb(eth_asic_base + WD_MSR, WD_MSR_MENB);
inb(0x84);
}
inb(0x84);
#ifdef NETBOOT32
net_bcopy(d, (void *)eth_bmem, ETHER_ADDR_SIZE); /* dst */
net_bcopy(nic->node_addr, (void *)eth_bmem+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE); /* src */
*((char *)eth_bmem+12) = t>>8; /* type */
*((char *)eth_bmem+13) = t;
net_bcopy(p, (void *)eth_bmem+ETHER_HDR_SIZE, s);
s += ETHER_HDR_SIZE;
while (s < ETH_MIN_PACKET) *((char *)eth_bmem+(s++)) = 0;
#endif
#ifdef NETBOOT16
bcopyf(d, eth_bmem, ETHER_ADDR_SIZE);
bcopyf(nic->node_addr, eth_bmem+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE);
c = t >> 8;
/* bcc generates worse code without (const+const) below */
bcopyf(&c, eth_bmem+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE), 1);
c = t;
bcopyf(&c, eth_bmem+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE+1), 1);
bcopyf(p, (Address)(eth_bmem+ETHER_HDR_SIZE), s);
s += ETHER_HDR_SIZE;
if (s < ETH_MIN_PACKET)
bzerof(eth_bmem+s, ETH_MIN_PACKET-s), s = ETH_MIN_PACKET;
#endif
if (eth_flags & FLAG_790) {
outb(eth_asic_base + WD_MSR, 0);
inb(0x84);
}
if (eth_flags & FLAG_16BIT) {
outb(eth_asic_base + WD_LAAR, eth_laar & ~WD_LAAR_M16EN);
inb(0x84);
}
}
#endif
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI)
if (eth_vendor == VENDOR_NOVELL) { /* Programmed I/O */
unsigned short type;
type = (t >> 8) | (t << 8);
eth_pio_write(d, eth_tx_start<<8, ETHER_ADDR_SIZE);
eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE);
/* bcc generates worse code without (const+const) below */
eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE), 2);
eth_pio_write(p, (eth_tx_start<<8)+ETHER_HDR_SIZE, s);
s += ETHER_HDR_SIZE;
if (s < ETH_MIN_PACKET) s = ETH_MIN_PACKET;
}
#endif
if (eth_flags & FLAG_790)
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 |
D8390_COMMAND_STA);
else
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 |
D8390_COMMAND_RD2 | D8390_COMMAND_STA);
outb(eth_nic_base+D8390_P0_TPSR, eth_tx_start);
outb(eth_nic_base+D8390_P0_TBCR0, s);
outb(eth_nic_base+D8390_P0_TBCR1, s>>8);
if (eth_flags & FLAG_790)
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 |
D8390_COMMAND_TXP | D8390_COMMAND_STA);
else
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 |
D8390_COMMAND_TXP | D8390_COMMAND_RD2 |
D8390_COMMAND_STA);
}
/**************************************************************************
ETH_POLL - Wait for a frame
**************************************************************************/
static int eth_poll(struct nic *nic)
{
int ret = 0;
unsigned char rstat, curr, next;
unsigned short len, frag;
unsigned short pktoff;
unsigned char *p;
struct ringbuffer pkthdr;
rstat = inb(eth_nic_base+D8390_P0_RSR);
if (rstat & D8390_RSTAT_OVER) {
eth_reset(nic);
return(0);
}
if (!(rstat & D8390_RSTAT_PRX)) return(0);
next = inb(eth_nic_base+D8390_P0_BOUND)+1;
if (next >= eth_memsize) next = eth_rx_start;
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1);
curr = inb(eth_nic_base+D8390_P1_CURR);
outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0);
if (curr >= eth_memsize) curr=eth_rx_start;
if (curr == next) return(0);
if (eth_vendor == VENDOR_WD) {
if (eth_flags & FLAG_16BIT) {
outb(eth_asic_base + WD_LAAR, eth_laar | WD_LAAR_M16EN);
inb(0x84);
}
if (eth_flags & FLAG_790) {
outb(eth_asic_base + WD_MSR, WD_MSR_MENB);
inb(0x84);
}
inb(0x84);
}
pktoff = next << 8;
if (eth_flags & FLAG_PIO)
eth_pio_read(pktoff, (char *)&pkthdr, 4);
else
#ifdef NETBOOT32
net_bcopy((void *)eth_rmem + pktoff, &pkthdr, 4);
#endif
#ifdef NETBOOT16
fnet_bcopy(eth_rmem + pktoff, &pkthdr, 4);
#endif
pktoff += sizeof(pkthdr);
len = pkthdr.len - 4; /* sub CRC */
if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || pkthdr.len < ETH_MIN_PACKET || pkthdr.len > ETH_MAX_PACKET) {
printf("B");
return (0);
}
else {
p = nic->packet;
nic->packetlen = len; /* available to caller */
frag = (eth_memsize << 8) - pktoff;
if (len > frag) { /* We have a wrap-around */
/* read first part */
if (eth_flags & FLAG_PIO)
eth_pio_read(pktoff, p, frag);
else
#ifdef NETBOOT32
net_bcopy((void *)eth_rmem + pktoff, p, frag);
#endif
#ifdef NETBOOT16
fnet_bcopy(eth_rmem + pktoff, p, frag);
#endif
pktoff = eth_rx_start << 8;
p += frag;
len -= frag;
}
/* read second part */
if (eth_flags & FLAG_PIO)
eth_pio_read(pktoff, p, len);
else
#ifdef NETBOOT32
net_bcopy((void *)eth_rmem + pktoff, p, len);
#endif
#ifdef NETBOOT16
fnet_bcopy(eth_rmem + pktoff, p, len);
#endif
ret = 1;
}
if (eth_vendor == VENDOR_WD) {
if (eth_flags & FLAG_790) {
outb(eth_asic_base + WD_MSR, 0);
inb(0x84);
}
if (eth_flags & FLAG_16BIT) {
outb(eth_asic_base + WD_LAAR, eth_laar &
~WD_LAAR_M16EN);
inb(0x84);
}
inb(0x84);
}
next = pkthdr.next; /* frame number of next packet */
if (next == eth_rx_start)
next = eth_memsize;
outb(eth_nic_base+D8390_P0_BOUND, next-1);
return(ret);
}
/**************************************************************************
ETH_DISABLE - Turn off adapter
**************************************************************************/
static void eth_disable(struct nic *nic)
{
}
/**************************************************************************
ETH_PROBE - Look for an adapter
**************************************************************************/
struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
{
int i;
struct wd_board *brd;
unsigned short chksum;
unsigned char c;
#if defined(INCLUDE_WD) && defined(NETBOOT16)
unsigned char bmem13, bmem11;
#endif
eth_vendor = VENDOR_NONE;
#ifdef INCLUDE_WD
/******************************************************************
Search for WD/SMC cards
******************************************************************/
for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;
eth_asic_base += 0x20) {
chksum = 0;
for (i=8; i<16; i++)
chksum += inb(i+eth_asic_base);
if ((chksum & 0x00FF) == 0x00FF)
break;
}
if (eth_asic_base <= WD_HIGH_BASE) { /* We've found a board */
eth_vendor = VENDOR_WD;
eth_nic_base = eth_asic_base + WD_NIC_ADDR;
c = inb(eth_asic_base+WD_BID); /* Get board id */
for (brd = wd_boards; brd->name; brd++)
if (brd->id == c) break;
if (!brd->name) {
printf("\r\nUnknown Ethernet type %x\r\n", c);
return(0); /* Unknown type */
}
eth_flags = brd->flags;
eth_memsize = brd->memsize;
eth_tx_start = 0;
eth_rx_start = D8390_TXBUF_SIZE;
if ((c == TYPE_WD8013EP) &&
(inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {
eth_flags = FLAG_16BIT;
eth_memsize = MEM_16384;
}
if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
#ifdef NETBOOT32
eth_bmem = (0x80000 |
((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
#endif
#ifdef NETBOOT16
eth_bmem = inb(eth_asic_base + WD_MSR) & 0x3F;
eth_bmem <<= 13;
eth_bmem |= 0x80000;
#endif
} else
eth_bmem = WD_DEFAULT_MEM;
#ifdef NETBOOT16
/* cast is to force evaluation in long precision */
bmem13 = (Address)eth_bmem >> 13;
bmem11 = (Address)eth_bmem >> 11;
#endif
#ifdef NETBOOT32
if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
*((unsigned int *)(eth_bmem + 8192)) = (unsigned int)0;
if (*((unsigned int *)(eth_bmem + 8192))) {
brd += 2;
eth_memsize = brd->memsize;
}
}
#endif
#ifdef NETBOOT16
if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
i = 0;
bcopyf(&i, eth_bmem + 8192, sizeof(i));
if (!fbsame(eth_bmem + 8192, 0, sizeof(i))) {
brd += 2;
eth_memsize = brd->memsize;
}
}
#endif
outb(eth_asic_base + WD_MSR, 0x80); /* Reset */
printf("\r\n%s base 0x%x, memory 0x%x, addr ",
brd->name, eth_asic_base, eth_bmem);
for (i=0; i<ETHER_ADDR_SIZE; i++) {
printf("%x",((int)(nic->node_addr[i] =
inb(i+eth_asic_base+WD_LAR)) & 0xff));
if (i < ETHER_ADDR_SIZE-1) printf (":");
}
if (eth_flags & FLAG_790) {
outb(eth_asic_base+WD_MSR, WD_MSR_MENB);
outb(eth_asic_base+0x04, (inb(eth_asic_base+0x04) |
0x80));
#ifdef NETBOOT32
outb(eth_asic_base+0x0B,
(((unsigned)eth_bmem >> 13) & 0x0F) |
(((unsigned)eth_bmem >> 11) & 0x40) |
(inb(eth_asic_base+0x0B) & 0xB0));
#endif
#ifdef NETBOOT16
outb(eth_asic_base+0x0B,
(bmem13 & 0x0F) |
(bmem11 & 0x40) |
(inb(eth_asic_base+0x0B) & 0xB0));
#endif
outb(eth_asic_base+0x04, (inb(eth_asic_base+0x04) &
~0x80));
} else {
#ifdef NETBOOT32
outb(eth_asic_base+WD_MSR,
(((unsigned)eth_bmem >> 13) & 0x3F) | 0x40);
#endif
#ifdef NETBOOT16
outb(eth_asic_base+WD_MSR,
(bmem13 & 0x3F) | 0x40);
#endif
}
if (eth_flags & FLAG_16BIT) {
if (eth_flags & FLAG_790) {
eth_laar = inb(eth_asic_base + WD_LAAR);
outb(eth_asic_base + WD_LAAR, WD_LAAR_M16EN);
inb(0x84);
} else {
outb(eth_asic_base + WD_LAAR, (eth_laar =
WD_LAAR_M16EN | WD_LAAR_L16EN | 1));
}
}
printf("\r\n");
}
#endif
#ifdef INCLUDE_T503
/******************************************************************
Search for 3Com 3c503 if no WD/SMC cards
******************************************************************/
if (eth_vendor == VENDOR_NONE) {
int idx;
static unsigned short base[] = {
0x300, 0x310, 0x330, 0x350,
0x250, 0x280, 0x2A0, 0x2E0, 0 };
/* this must parallel the table above */
static unsigned char bcfr[] = {
_3COM_BCFR_300, _3COM_BCFR_310,
_3COM_BCFR_330, _3COM_BCFR_350,
_3COM_BCFR_250, _3COM_BCFR_280,
_3COM_BCFR_2A0, _3COM_BCFR_2E0, 0 };
/* Loop through possible addresses checking each one */
for (idx = 0; (eth_nic_base = base[idx]) != 0; ++idx) {
eth_asic_base = eth_nic_base + _3COM_ASIC_OFFSET;
/*
* Note that we use the same settings for both 8 and 16 bit cards:
* both have an 8K bank of memory at page 1 while only the 16 bit
* cards have a bank at page 0.
*/
eth_memsize = MEM_16384;
eth_tx_start = 32;
eth_rx_start = 32 + D8390_TXBUF_SIZE;
/* Check our base address */
if (inb(eth_asic_base + _3COM_BCFR) != bcfr[idx])
continue; /* nope */
/* Now get the shared memory address */
switch (inb(eth_asic_base + _3COM_PCFR)) {
case _3COM_PCFR_DC000:
eth_bmem = 0xdc000;
break;
case _3COM_PCFR_D8000:
eth_bmem = 0xd8000;
break;
case _3COM_PCFR_CC000:
eth_bmem = 0xcc000;
break;
case _3COM_PCFR_C8000:
eth_bmem = 0xc8000;
break;
default:
continue; /* nope */
}
break;
}
if (base[idx] == 0) /* not found */
return (0);
eth_vendor = VENDOR_3COM;
/* Need this to make eth_poll() happy. */
eth_rmem = eth_bmem - 0x2000;
/* Reset NIC and ASIC */
outb (eth_asic_base + _3COM_CR , _3COM_CR_RST | _3COM_CR_XSEL);
outb (eth_asic_base + _3COM_CR , _3COM_CR_XSEL);
/* Get our ethernet address */
outb(eth_asic_base + _3COM_CR, _3COM_CR_EALO | _3COM_CR_XSEL);
printf("\r\n3Com 3c503 base 0x%x, memory 0x%X addr ",
eth_nic_base, eth_bmem);
for (i=0; i<ETHER_ADDR_SIZE; i++) {
printf("%b",(int)(nic->node_addr[i] =
inb(eth_nic_base+i)));
if (i < ETHER_ADDR_SIZE-1) printf (":");
}
outb(eth_asic_base + _3COM_CR, _3COM_CR_XSEL);
/*
* Initialize GA configuration register. Set bank and enable shared
* mem. We always use bank 1.
*/
outb(eth_asic_base + _3COM_GACFR, _3COM_GACFR_RSEL |
_3COM_GACFR_MBS0);
outb(eth_asic_base + _3COM_VPTR2, 0xff);
outb(eth_asic_base + _3COM_VPTR1, 0xff);
outb(eth_asic_base + _3COM_VPTR0, 0x00);
/*
* Clear memory and verify that it worked (we use only 8K)
*/
#ifdef NETBOOT32
bzero((char *)eth_bmem, 0x2000);
for(i = 0; i < 0x2000; ++i)
if (*(((char *)eth_bmem)+i)) {
printf ("Failed to clear 3c503 shared mem.\r\n");
return (0);
}
#endif
#ifdef NETBOOT16
bzerof(eth_bmem, 0x2000);
if (!fbsame(eth_bmem, 0, 0x2000)) {
printf ("Failed to clear 3c503 shared mem.\r\n");
return (0);
}
#endif
/*
* Initialize GA page/start/stop registers.
*/
outb(eth_asic_base + _3COM_PSTR, eth_tx_start);
outb(eth_asic_base + _3COM_PSPR, eth_memsize);
printf ("\r\n");
}
#endif
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI)
/******************************************************************
Search for NE1000/2000 if no WD/SMC or 3com cards
******************************************************************/
if (eth_vendor == VENDOR_NONE) {
char romdata[16], testbuf[32];
int idx;
static char test[] = "NE1000/2000 memory";
#ifndef NE_SCAN
#define NE_SCAN 0
#endif
static unsigned short base[] = {NE_SCAN, 0};
/* if no addresses supplied, fall back on defaults */
if (probe_addrs == 0 || probe_addrs[0] == 0)
probe_addrs = base;
eth_bmem = 0; /* No shared memory */
for (idx = 0; (eth_nic_base = probe_addrs[idx]) != 0; ++idx) {
eth_flags = FLAG_PIO;
eth_asic_base = eth_nic_base + NE_ASIC_OFFSET;
eth_memsize = MEM_16384;
eth_tx_start = 32;
eth_rx_start = 32 + D8390_TXBUF_SIZE;
c = inb(eth_asic_base + NE_RESET);
outb(eth_asic_base + NE_RESET, c);
inb(0x84);
outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_STP |
D8390_COMMAND_RD2);
outb(eth_nic_base + D8390_P0_RCR, D8390_RCR_MON);
outb(eth_nic_base + D8390_P0_DCR, D8390_DCR_FT1 | D8390_DCR_LS);
outb(eth_nic_base + D8390_P0_PSTART, MEM_8192);
outb(eth_nic_base + D8390_P0_PSTOP, MEM_16384);
eth_pio_write(test, 8192, sizeof(test));
eth_pio_read(8192, testbuf, sizeof(test));
if (!bcmp(test, testbuf, sizeof(test)))
break;
eth_flags |= FLAG_16BIT;
eth_memsize = MEM_32768;
eth_tx_start = 64;
eth_rx_start = 64 + D8390_TXBUF_SIZE;
outb(eth_nic_base + D8390_P0_DCR, D8390_DCR_WTS |
D8390_DCR_FT1 | D8390_DCR_LS);
outb(eth_nic_base + D8390_P0_PSTART, MEM_16384);
outb(eth_nic_base + D8390_P0_PSTOP, MEM_32768);
eth_pio_write(test, 16384, sizeof(test));
eth_pio_read(16384, testbuf, sizeof(test));
if (!bcmp(testbuf, test, sizeof(test)))
break;
}
if (eth_nic_base == 0)
return (0);
if (eth_nic_base > ISA_MAX_ADDR) /* PCI probably */
eth_flags |= FLAG_16BIT;
eth_vendor = VENDOR_NOVELL;
eth_pio_read(0, romdata, 16);
printf("\r\nNE*000 base 0x%x, addr ", eth_nic_base);
for (i=0; i<ETHER_ADDR_SIZE; i++) {
printf("%x",(int)(nic->node_addr[i] = romdata[i
+ ((eth_flags & FLAG_16BIT) ? i : 0)]));
if (i < ETHER_ADDR_SIZE-1) printf (":");
}
printf("\r\n");
}
#endif
if (eth_vendor == VENDOR_NONE) return(0);
if (eth_vendor != VENDOR_3COM) eth_rmem = eth_bmem;
eth_reset(nic);
nic->reset = eth_reset;
nic->poll = eth_poll;
nic->transmit = eth_transmit;
nic->disable = eth_disable;
return(nic);
}
#endif
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

251
netboot/ns8390.h Normal file
View file

@ -0,0 +1,251 @@
/**************************************************************************
NETBOOT - BOOTP/TFTP Bootstrap Program
Author: Martin Renters
Date: Jun/94
**************************************************************************/
#define MEM_8192 32
#define MEM_16384 64
#define MEM_32768 128
#define ISA_MAX_ADDR 0x400
/**************************************************************************
Western Digital/SMC Board Definitions
**************************************************************************/
#define WD_LOW_BASE 0x200
#define WD_HIGH_BASE 0x3e0
#ifndef WD_DEFAULT_MEM
#define WD_DEFAULT_MEM 0xD0000
#endif
#define WD_NIC_ADDR 0x10
/**************************************************************************
Western Digital/SMC ASIC Addresses
**************************************************************************/
#define WD_MSR 0x00
#define WD_ICR 0x01
#define WD_IAR 0x02
#define WD_BIO 0x03
#define WD_IRR 0x04
#define WD_LAAR 0x05
#define WD_IJR 0x06
#define WD_GP2 0x07
#define WD_LAR 0x08
#define WD_BID 0x0E
#define WD_ICR_16BIT 0x01
#define WD_MSR_MENB 0x40
#define WD_LAAR_L16EN 0x40
#define WD_LAAR_M16EN 0x80
#define WD_SOFTCONFIG 0x20
/**************************************************************************
Western Digital/SMC Board Types
**************************************************************************/
#define TYPE_WD8003S 0x02
#define TYPE_WD8003E 0x03
#define TYPE_WD8013EBT 0x05
#define TYPE_WD8003W 0x24
#define TYPE_WD8003EB 0x25
#define TYPE_WD8013W 0x26
#define TYPE_WD8013EP 0x27
#define TYPE_WD8013WC 0x28
#define TYPE_WD8013EPC 0x29
#define TYPE_SMC8216T 0x2a
#define TYPE_SMC8216C 0x2b
#define TYPE_SMC8416T 0x00 /* Bogus entries: the 8416 generates the */
#define TYPE_SMC8416C 0x00 /* the same codes as the 8216. */
#define TYPE_SMC8013EBP 0x2c
#ifdef INCLUDE_WD
struct wd_board {
char *name;
char id;
char flags;
char memsize;
} wd_boards[] = {
{"WD8003S", TYPE_WD8003S, 0, MEM_8192},
{"WD8003E", TYPE_WD8003E, 0, MEM_8192},
{"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384},
{"WD8003W", TYPE_WD8003W, 0, MEM_8192},
{"WD8003EB", TYPE_WD8003EB, 0, MEM_8192},
{"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384},
{"WD8003EP/WD8013EP",
TYPE_WD8013EP, 0, MEM_8192},
{"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384},
{"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384},
{"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384},
{"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384},
{"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192},
{"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192},
{"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384},
{NULL, 0, 0}
};
#endif
/**************************************************************************
3com 3c503 definitions
**************************************************************************/
#ifndef _3COM_BASE
#define _3COM_BASE 0x300
#endif
#define _3COM_TX_PAGE_OFFSET_8BIT 0x20
#define _3COM_TX_PAGE_OFFSET_16BIT 0x0
#define _3COM_RX_PAGE_OFFSET_16BIT 0x20
#define _3COM_ASIC_OFFSET 0x400
#define _3COM_NIC_OFFSET 0x0
#define _3COM_PSTR 0
#define _3COM_PSPR 1
#define _3COM_BCFR 3
#define _3COM_BCFR_2E0 0x01
#define _3COM_BCFR_2A0 0x02
#define _3COM_BCFR_280 0x04
#define _3COM_BCFR_250 0x08
#define _3COM_BCFR_350 0x10
#define _3COM_BCFR_330 0x20
#define _3COM_BCFR_310 0x40
#define _3COM_BCFR_300 0x80
#define _3COM_PCFR 4
#define _3COM_PCFR_C8000 0x10
#define _3COM_PCFR_CC000 0x20
#define _3COM_PCFR_D8000 0x40
#define _3COM_PCFR_DC000 0x80
#define _3COM_CR 6
#define _3COM_CR_RST 0x01 /* Reset GA and NIC */
#define _3COM_CR_XSEL 0x02 /* Transceiver select. BNC=1(def) AUI=0 */
#define _3COM_CR_EALO 0x04 /* window EA PROM 0-15 to I/O base */
#define _3COM_CR_EAHI 0x08 /* window EA PROM 16-31 to I/O base */
#define _3COM_CR_SHARE 0x10 /* select interrupt sharing option */
#define _3COM_CR_DBSEL 0x20 /* Double buffer select */
#define _3COM_CR_DDIR 0x40 /* DMA direction select */
#define _3COM_CR_START 0x80 /* Start DMA controller */
#define _3COM_GACFR 5
#define _3COM_GACFR_MBS0 0x01
#define _3COM_GACFR_MBS1 0x02
#define _3COM_GACFR_MBS2 0x04
#define _3COM_GACFR_RSEL 0x08 /* enable shared memory */
#define _3COM_GACFR_TEST 0x10 /* for GA testing */
#define _3COM_GACFR_OWS 0x20 /* select 0WS access to GA */
#define _3COM_GACFR_TCM 0x40 /* Mask DMA interrupts */
#define _3COM_GACFR_NIM 0x80 /* Mask NIC interrupts */
#define _3COM_STREG 7
#define _3COM_STREG_REV 0x07 /* GA revision */
#define _3COM_STREG_DIP 0x08 /* DMA in progress */
#define _3COM_STREG_DTC 0x10 /* DMA terminal count */
#define _3COM_STREG_OFLW 0x20 /* Overflow */
#define _3COM_STREG_UFLW 0x40 /* Underflow */
#define _3COM_STREG_DPRDY 0x80 /* Data port ready */
#define _3COM_IDCFR 8
#define _3COM_IDCFR_DRQ0 0x01 /* DMA request 1 select */
#define _3COM_IDCFR_DRQ1 0x02 /* DMA request 2 select */
#define _3COM_IDCFR_DRQ2 0x04 /* DMA request 3 select */
#define _3COM_IDCFR_UNUSED 0x08 /* not used */
#define _3COM_IDCFR_IRQ2 0x10 /* Interrupt request 2 select */
#define _3COM_IDCFR_IRQ3 0x20 /* Interrupt request 3 select */
#define _3COM_IDCFR_IRQ4 0x40 /* Interrupt request 4 select */
#define _3COM_IDCFR_IRQ5 0x80 /* Interrupt request 5 select */
#define _3COM_IRQ2 2
#define _3COM_IRQ3 3
#define _3COM_IRQ4 4
#define _3COM_IRQ5 5
#define _3COM_DAMSB 9
#define _3COM_DALSB 0x0a
#define _3COM_VPTR2 0x0b
#define _3COM_VPTR1 0x0c
#define _3COM_VPTR0 0x0d
#define _3COM_RFMSB 0x0e
#define _3COM_RFLSB 0x0f
/**************************************************************************
NE1000/2000 definitions
**************************************************************************/
#define NE_ASIC_OFFSET 0x10
#define NE_RESET 0x0F /* Used to reset card */
#define NE_DATA 0x00 /* Used to read/write NIC mem */
/**************************************************************************
8390 Register Definitions
**************************************************************************/
#define D8390_P0_COMMAND 0x00
#define D8390_P0_PSTART 0x01
#define D8390_P0_PSTOP 0x02
#define D8390_P0_BOUND 0x03
#define D8390_P0_TSR 0x04
#define D8390_P0_TPSR 0x04
#define D8390_P0_TBCR0 0x05
#define D8390_P0_TBCR1 0x06
#define D8390_P0_ISR 0x07
#define D8390_P0_RSAR0 0x08
#define D8390_P0_RSAR1 0x09
#define D8390_P0_RBCR0 0x0A
#define D8390_P0_RBCR1 0x0B
#define D8390_P0_RSR 0x0C
#define D8390_P0_RCR 0x0C
#define D8390_P0_TCR 0x0D
#define D8390_P0_DCR 0x0E
#define D8390_P0_IMR 0x0F
#define D8390_P1_COMMAND 0x00
#define D8390_P1_PAR0 0x01
#define D8390_P1_PAR1 0x02
#define D8390_P1_PAR2 0x03
#define D8390_P1_PAR3 0x04
#define D8390_P1_PAR4 0x05
#define D8390_P1_PAR5 0x06
#define D8390_P1_CURR 0x07
#define D8390_P1_MAR0 0x08
#define D8390_COMMAND_PS0 0x0 /* Page 0 select */
#define D8390_COMMAND_PS1 0x40 /* Page 1 select */
#define D8390_COMMAND_PS2 0x80 /* Page 2 select */
#define D8390_COMMAND_RD2 0x20 /* Remote DMA control */
#define D8390_COMMAND_RD1 0x10
#define D8390_COMMAND_RD0 0x08
#define D8390_COMMAND_TXP 0x04 /* transmit packet */
#define D8390_COMMAND_STA 0x02 /* start */
#define D8390_COMMAND_STP 0x01 /* stop */
#define D8390_RCR_MON 0x20 /* monitor mode */
#define D8390_DCR_FT1 0x40
#define D8390_DCR_LS 0x08 /* Loopback select */
#define D8390_DCR_WTS 0x01 /* Word transfer select */
#define D8390_ISR_PRX 0x01 /* successful recv */
#define D8390_ISR_PTX 0x02 /* successful xmit */
#define D8390_ISR_RXE 0x04 /* receive error */
#define D8390_ISR_TXE 0x08 /* transmit error */
#define D8390_ISR_OVW 0x10 /* Overflow */
#define D8390_ISR_CNT 0x20 /* Counter overflow */
#define D8390_ISR_RDC 0x40 /* Remote DMA complete */
#define D8390_ISR_RST 0x80 /* reset */
#define D8390_RSTAT_PRX 0x01 /* successful recv */
#define D8390_RSTAT_CRC 0x02 /* CRC error */
#define D8390_RSTAT_FAE 0x04 /* Frame alignment error */
#define D8390_RSTAT_OVER 0x08 /* overflow */
#define D8390_TXBUF_SIZE 6
#define D8390_RXBUF_END 32
#define D8390_PAGE_SIZE 256
struct ringbuffer {
unsigned char status;
unsigned char next;
unsigned short len;
};
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

261
netboot/pci.c Normal file
View file

@ -0,0 +1,261 @@
/*
** Support for NE2000 PCI clones added David Monro June 1997
** Generalised to other NICs by Ken Yap July 1997
**
** Most of this is taken from:
**
** /usr/src/linux/drivers/pci/pci.c
** /usr/src/linux/include/linux/pci.h
** /usr/src/linux/arch/i386/bios32.c
** /usr/src/linux/include/linux/bios32.h
** /usr/src/linux/drivers/net/ne.c
**
** Limitations: only finds devices on bus 0 (I figure that anybody with
** a multi-pcibus machine will have something better than an ne2000)
*/
#include "netboot.h"
#include "pci.h"
#define DEBUG 1
static unsigned int pci_ioaddr = 0;
static unsigned long bios32_entry = 0;
static struct {
unsigned long address;
unsigned short segment;
} bios32_indirect = { 0, KERN_CODE_SEG };
static long pcibios_entry = 0;
static struct {
unsigned long address;
unsigned short segment;
} pci_indirect = { 0, KERN_CODE_SEG };
static unsigned long bios32_service(unsigned long service)
{
unsigned char return_code; /* %al */
unsigned long address; /* %ebx */
unsigned long length; /* %ecx */
unsigned long entry; /* %edx */
unsigned long flags;
save_flags(flags);
__asm__("lcall (%%edi)"
: "=a" (return_code),
"=b" (address),
"=c" (length),
"=d" (entry)
: "0" (service),
"1" (0),
"D" (&bios32_indirect));
restore_flags(flags);
switch (return_code) {
case 0:
return address + entry;
case 0x80: /* Not present */
printf("bios32_service(%d) : not present\r\n", service);
return 0;
default: /* Shouldn't happen */
printf("bios32_service(%d) : returned 0x%x, mail drew@colorado.edu\r\n",
service, return_code);
return 0;
}
}
static int pcibios_read_config_byte(unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned char *value)
{
unsigned long ret;
unsigned long bx = (bus << 8) | device_fn;
unsigned long flags;
save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=c" (*value),
"=a" (ret)
: "1" (PCIBIOS_READ_CONFIG_BYTE),
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}
static int pcibios_read_config_dword (unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned int *value)
{
unsigned long ret;
unsigned long bx = (bus << 8) | device_fn;
unsigned long flags;
save_flags(flags);
__asm__("lcall (%%esi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:"
: "=c" (*value),
"=a" (ret)
: "1" (PCIBIOS_READ_CONFIG_DWORD),
"b" (bx),
"D" ((long) where),
"S" (&pci_indirect));
restore_flags(flags);
return (int) (ret & 0xff00) >> 8;
}
static void check_pcibios(void)
{
unsigned long signature;
unsigned char present_status;
unsigned char major_revision;
unsigned char minor_revision;
unsigned long flags;
int pack;
if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
pci_indirect.address = pcibios_entry;
save_flags(flags);
__asm__("lcall (%%edi)\n\t"
"jc 1f\n\t"
"xor %%ah, %%ah\n"
"1:\tshl $8, %%eax\n\t"
"movw %%bx, %%ax"
: "=d" (signature),
"=a" (pack)
: "1" (PCIBIOS_PCI_BIOS_PRESENT),
"D" (&pci_indirect)
: "bx", "cx");
restore_flags(flags);
present_status = (pack >> 16) & 0xff;
major_revision = (pack >> 8) & 0xff;
minor_revision = pack & 0xff;
if (present_status || (signature != PCI_SIGNATURE)) {
printf("ERROR: BIOS32 says PCI BIOS, but no PCI "
"BIOS????\r\n");
pcibios_entry = 0;
}
#if DEBUG
if (pcibios_entry) {
printf ("pcibios_init : PCI BIOS revision %b.%b"
" entry at 0x%X\r\n", major_revision,
minor_revision, pcibios_entry);
}
#endif
}
}
static void pcibios_init(void)
{
union bios32 *check;
unsigned char sum;
int i, length;
/*
* Follow the standard procedure for locating the BIOS32 Service
* directory by scanning the permissible address range from
* 0xe0000 through 0xfffff for a valid BIOS32 structure.
*
*/
for (check = (union bios32 *) 0xe0000; check <= (union bios32 *) 0xffff0; ++check) {
if (check->fields.signature != BIOS32_SIGNATURE)
continue;
length = check->fields.length * 16;
if (!length)
continue;
sum = 0;
for (i = 0; i < length ; ++i)
sum += check->chars[i];
if (sum != 0)
continue;
if (check->fields.revision != 0) {
printf("pcibios_init : unsupported revision %d at 0x%X, mail drew@colorado.edu\r\n",
check->fields.revision, check);
continue;
}
#if DEBUG
printf("pcibios_init : BIOS32 Service Directory "
"structure at 0x%X\r\n", check);
#endif
if (!bios32_entry) {
if (check->fields.entry >= 0x100000) {
printf("pcibios_init: entry in high "
"memory, giving up\r\n");
return;
} else {
bios32_entry = check->fields.entry;
#if DEBUG
printf("pcibios_init : BIOS32 Service Directory"
" entry at 0x%X\r\n", bios32_entry);
#endif
bios32_indirect.address = bios32_entry;
}
}
}
if (bios32_entry)
check_pcibios();
}
static void scan_bus(struct pci_device *pcidev)
{
unsigned int devfn, l;
unsigned char hdr_type = 0;
unsigned short vendor, device;
int i;
for (devfn = 0; devfn < 0xff; ++devfn) {
if (PCI_FUNC(devfn) == 0) {
pcibios_read_config_byte(0, devfn,
PCI_HEADER_TYPE, &hdr_type);
} else if (!(hdr_type & 0x80)) {
/* not a multi-function device */
continue;
}
pcibios_read_config_dword(0, devfn,
PCI_VENDOR_ID, &l);
/* some broken boards return 0 if a slot is empty: */
if (l == 0xffffffff || l == 0x00000000) {
hdr_type = 0;
continue;
}
vendor = l & 0xffff;
device = (l >> 16) & 0xffff;
#if DEBUG
printf("bus 0, function %x, vendor %x, device %x\r\n",
devfn, vendor, device);
#endif
for (i = 0; pcidev[i].vendor != 0; i++) {
if (vendor == pcidev[i].vendor
&& device == pcidev[i].dev_id) {
pcibios_read_config_dword(0, devfn,
PCI_BASE_ADDRESS_0, &pci_ioaddr);
/* Strip the I/O address out of the
* returned value */
pci_ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
printf("Found %s at 0x%x\r\n",
pcidev[i].name, pci_ioaddr);
}
}
}
}
void eth_pci_init(struct pci_device *pcidev, unsigned short *ioaddr)
{
pcibios_init();
if (!pcibios_entry) {
printf("pci_init: no BIOS32 detected\r\n");
return;
}
scan_bus(pcidev);
/* we only return one address at the moment, maybe more later? */
*ioaddr = pci_ioaddr;
}

89
netboot/pci.h Normal file
View file

@ -0,0 +1,89 @@
/*
** Support for NE2000 PCI clones added David Monro June 1997
** Generalised for other PCI NICs by Ken Yap July 1997
**
** Most of this is taken from:
**
** /usr/src/linux/drivers/pci/pci.c
** /usr/src/linux/include/linux/pci.h
** /usr/src/linux/arch/i386/bios32.c
** /usr/src/linux/include/linux/bios32.h
** /usr/src/linux/drivers/net/ne.c
*/
#define PCIBIOS_PCI_FUNCTION_ID 0xb1XX
#define PCIBIOS_PCI_BIOS_PRESENT 0xb101
#define PCIBIOS_FIND_PCI_DEVICE 0xb102
#define PCIBIOS_FIND_PCI_CLASS_CODE 0xb103
#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0xb106
#define PCIBIOS_READ_CONFIG_BYTE 0xb108
#define PCIBIOS_READ_CONFIG_WORD 0xb109
#define PCIBIOS_READ_CONFIG_DWORD 0xb10a
#define PCIBIOS_WRITE_CONFIG_BYTE 0xb10b
#define PCIBIOS_WRITE_CONFIG_WORD 0xb10c
#define PCIBIOS_WRITE_CONFIG_DWORD 0xb10d
#define PCI_VENDOR_ID 0x00 /* 16 bits */
#define PCI_DEVICE_ID 0x02 /* 16 bits */
#define PCI_COMMAND 0x04 /* 16 bits */
#define PCI_HEADER_TYPE 0x0e /* 8 bits */
#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
#define PCI_BASE_ADDRESS_IO_MASK (~0x03)
#define PCI_FUNC(devfn) ((devfn) & 0x07)
#define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
/* PCI signature: "PCI " */
#define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
/* PCI service signature: "$PCI" */
#define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
union bios32 {
struct {
unsigned long signature; /* _32_ */
unsigned long entry; /* 32 bit physical address */
unsigned char revision; /* Revision level, 0 */
unsigned char length; /* Length in paragraphs should be 01 */
unsigned char checksum; /* All bytes must add up to zero */
unsigned char reserved[5]; /* Must be zero */
} fields;
char chars[16];
};
#define KERN_CODE_SEG 0x8 /* This _MUST_ match start.S */
/* Stuff for asm */
#define save_flags(x) \
__asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */ :"memory")
#define restore_flags(x) \
__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
#define PCI_VENDOR_ID_REALTEK 0x10ec
#define PCI_DEVICE_ID_REALTEK_8029 0x8029
#define PCI_VENDOR_ID_WINBOND2 0x1050
#define PCI_DEVICE_ID_WINBOND2_89C940 0x0940
#define PCI_VENDOR_ID_COMPEX 0x11f6
#define PCI_DEVICE_ID_COMPEX_RL2000 0x1401
#define PCI_VENDOR_ID_KTI 0x8e2e
#define PCI_DEVICE_ID_KTI_ET32P2 0x3000
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_82557 0x1229
#define PCI_VENDOR_ID_NETVIN 0x4a14
#define PCI_DEVICE_ID_NETVIN_NV5000SC 0x5000
#define PCI_VENDOR_ID_VIA 0x1106
#define PCI_DEVICE_ID_VIA_82C926 0x0926
#define PCI_VENDOR_ID_SURECOM 0x10bd
#define PCI_DEVICE_ID_SURECOM_NE34 0x0e34
struct pci_device {
unsigned short vendor, dev_id;
char *name;
};
extern void eth_pci_init(struct pci_device *, unsigned short *);

View file

@ -67,6 +67,8 @@ GRUB_LIBS = @GRUB_LIBS@
LD = @LD@ LD = @LD@
MAINT = @MAINT@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
NET_CFLAGS = @NET_CFLAGS@
NET_EXTRAFLAGS = @NET_EXTRAFLAGS@
OBJCOPY = @OBJCOPY@ OBJCOPY = @OBJCOPY@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
PERL = @PERL@ PERL = @PERL@

View file

@ -398,7 +398,7 @@ lastlist:
#else #else
.long 1 /* this is the sector start parameter, in logical .long 1 /* this is the sector start parameter, in logical
sectors from the start of the disk, sector 0 */ sectors from the start of the disk, sector 0 */
.word 110 /* this is the number of sectors to read */ .word 130 /* this is the number of sectors to read */
.word 0x0800 /* this is the segment of the starting address .word 0x0800 /* this is the segment of the starting address
to load the data into */ to load the data into */
#endif #endif

View file

@ -345,7 +345,7 @@ lastlist:
#else #else
.long 1 /* this is the sector start parameter, in logical .long 1 /* this is the sector start parameter, in logical
sectors from the start of the disk, sector 0 */ sectors from the start of the disk, sector 0 */
.word 110 /* this is the number of sectors to read */ .word 130 /* this is the number of sectors to read */
.word 0x0800 /* this is the segment of the starting address .word 0x0800 /* this is the segment of the starting address
to load the data into */ to load the data into */
#endif #endif

View file

@ -43,6 +43,10 @@ stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \
stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
stage2_exec_LDFLAGS = $(STAGE2_LINK) stage2_exec_LDFLAGS = $(STAGE2_LINK)
if NETBOOT_SUPPORT
stage2_exec_LDADD = ../netboot/libdrivers.a
endif
# For e2fs_stage1_5 target. # For e2fs_stage1_5 target.
e2fs_stage1_5_exec_SOURCES = asm.S common.c char_io.c disk_io.c \ e2fs_stage1_5_exec_SOURCES = asm.S common.c char_io.c disk_io.c \
stage1_5.c fsys_ext2fs.c bios.c stage1_5.c fsys_ext2fs.c bios.c

View file

@ -67,6 +67,8 @@ GRUB_LIBS = @GRUB_LIBS@
LD = @LD@ LD = @LD@
MAINT = @MAINT@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@ MAKEINFO = @MAKEINFO@
NET_CFLAGS = @NET_CFLAGS@
NET_EXTRAFLAGS = @NET_EXTRAFLAGS@
OBJCOPY = @OBJCOPY@ OBJCOPY = @OBJCOPY@
PACKAGE = @PACKAGE@ PACKAGE = @PACKAGE@
PERL = @PERL@ PERL = @PERL@
@ -132,6 +134,8 @@ stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \
stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
stage2_exec_LDFLAGS = $(STAGE2_LINK) stage2_exec_LDFLAGS = $(STAGE2_LINK)
@NETBOOT_SUPPORT_TRUE@stage2_exec_LDADD = @NETBOOT_SUPPORT_TRUE@../netboot/libdrivers.a
# For e2fs_stage1_5 target. # For e2fs_stage1_5 target.
e2fs_stage1_5_exec_SOURCES = asm.S common.c char_io.c disk_io.c \ e2fs_stage1_5_exec_SOURCES = asm.S common.c char_io.c disk_io.c \
stage1_5.c fsys_ext2fs.c bios.c stage1_5.c fsys_ext2fs.c bios.c
@ -223,8 +227,8 @@ stage2_exec-gunzip.o stage2_exec-fsys_ext2fs.o stage2_exec-fsys_fat.o \
stage2_exec-fsys_ffs.o stage2_exec-fsys_minix.o stage2_exec-smp-imps.o \ stage2_exec-fsys_ffs.o stage2_exec-fsys_minix.o stage2_exec-smp-imps.o \
stage2_exec-stage2.o stage2_exec-stage2.o
stage2_exec_OBJECTS = $(am_stage2_exec_OBJECTS) stage2_exec_OBJECTS = $(am_stage2_exec_OBJECTS)
stage2_exec_LDADD = $(LDADD) @NETBOOT_SUPPORT_TRUE@stage2_exec_DEPENDENCIES = \
stage2_exec_DEPENDENCIES = @NETBOOT_SUPPORT_TRUE@../netboot/libdrivers.a
SCRIPTS = $(noinst_SCRIPTS) SCRIPTS = $(noinst_SCRIPTS)
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)

View file

@ -1328,6 +1328,37 @@ gottime:
pop %ebp pop %ebp
ret ret
#ifndef STAGE1_5
/*
* currticks()
* return the real time in ticks, of which there are about
* 18-20 per second
*/
ENTRY(currticks)
pushl %ebp
pushl %ecx
pushl %edx
call EXT_C(prot_to_real) /* enter real mode */
.code16
xorl %eax, %eax
int $0x1a
DATA32 call EXT_C(real_to_prot)
.code32
shll $16, %ecx
movl %edx, %eax
orl %ecx, %eax
popl %edx
popl %ecx
popl %ebp
ret
#endif /* ! STAGE1_5 */
/* /*
* getkey() * getkey()

View file

@ -126,6 +126,53 @@ grub_printf (const char *format,...)
} }
#ifndef STAGE1_5
int
grub_sprintf (char *buffer, const char *format, ...)
{
/* XXX hohmuth
ugly hack -- should unify with printf() */
int *dataptr = (int *) &format;
char c, *ptr, str[16];
char *bp = buffer;
dataptr++;
while ((c = *format++) != 0)
{
if (c != '%')
*bp++ = c; /* putchar(c); */
else
switch (c = *(format++))
{
case 'd': case 'u': case 'x':
*convert_to_ascii (str, c, *((unsigned long *) dataptr++)) = 0;
ptr = str;
while (*ptr)
*bp++ = *(ptr++); /* putchar(*(ptr++)); */
break;
case 'c': *bp++ = (*(dataptr++))&0xff;
/* putchar((*(dataptr++))&0xff); */
break;
case 's':
ptr = (char *) (*(dataptr++));
while ((c = *ptr++) != 0)
*bp++ = c; /* putchar(c); */
break;
}
}
*bp = 0;
return bp - buffer;
}
#endif /* ! STAGE1_5 */
#ifndef STAGE1_5 #ifndef STAGE1_5
void void
@ -520,6 +567,24 @@ grub_isspace (int c)
return 0; return 0;
} }
#ifndef STAGE1_5
int
grub_memcmp (const char *s1, const char *s2, int n)
{
while (n)
{
if (*s1 < *s2)
return -1;
else if (*s1 > *s2)
return 1;
s1++;
s2++;
n--;
}
return 0;
}
#endif /* ! STAGE1_5 */
#if 0 #if 0
int int

View file

@ -35,6 +35,10 @@ int print_possibilities;
int fsmax; int fsmax;
struct fsys_entry fsys_table[NUM_FSYS + 1] = struct fsys_entry fsys_table[NUM_FSYS + 1] =
{ {
/* TFTP should come first because others don't handle net device. */
# ifdef FSYS_TFTP
{"tftp", tftp_mount, tftp_read, tftp_dir},
# endif
# ifdef FSYS_FAT # ifdef FSYS_FAT
{"fat", fat_mount, 0, fat_dir}, {"fat", fat_mount, 0, fat_dir},
# endif # endif
@ -236,6 +240,12 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
static int static int
sane_partition (void) sane_partition (void)
{ {
#ifndef STAGE1_5
/* network drive */
if (current_drive == 0x20)
return 1;
#endif
if (!(current_partition & 0xFF000000uL) if (!(current_partition & 0xFF000000uL)
&& (current_drive & 0xFFFFFF7F) < 8 && (current_drive & 0xFFFFFF7F) < 8
&& (current_partition & 0xFF) == 0xFF && (current_partition & 0xFF) == 0xFF
@ -440,6 +450,10 @@ real_open_partition (int flags)
int i, part_no, slice_no, ext = 0; int i, part_no, slice_no, ext = 0;
#ifndef STAGE1_5 #ifndef STAGE1_5
/* network drive */
if (current_drive == 0x20)
return 1;
if (! sane_partition ()) if (! sane_partition ())
return 0; return 0;
#endif #endif
@ -674,15 +688,20 @@ set_device (char *device)
} }
#endif #endif
if ((*device == 'f' || *device == 'h') if ((*device == 'f' || *device == 'h' || *device == 'n')
&& (device += 2, (*(device - 1) != 'd'))) && (device += 2, (*(device - 1) != 'd')))
errnum = ERR_NUMBER_PARSING; errnum = ERR_NUMBER_PARSING;
safe_parse_maxint (&device, (int *) &current_drive); if (ch == 'n')
current_drive = 0x20;
disk_choice = 0; else
if (ch == 'h') {
current_drive += 0x80; safe_parse_maxint (&device, (int *) &current_drive);
disk_choice = 0;
if (ch == 'h')
current_drive += 0x80;
}
} }
if (errnum) if (errnum)

View file

@ -60,9 +60,19 @@ int minix_dir (char *dirname);
#define FSYS_MINIX_NUM 0 #define FSYS_MINIX_NUM 0
#endif #endif
#ifdef FSYS_TFTP
#define FSYS_TFTP_NUM 1
int tftp_mount (void);
int tftp_read (char *buf, int len);
int tftp_dir (char *dirname);
#else
#define FSYS_TFTP_NUM 0
#endif
#ifndef NUM_FSYS #ifndef NUM_FSYS
#define NUM_FSYS \ #define NUM_FSYS \
(FSYS_FFS_NUM + FSYS_FAT_NUM + FSYS_EXT2FS_NUM + FSYS_MINIX_NUM) (FSYS_FFS_NUM + FSYS_FAT_NUM + FSYS_EXT2FS_NUM + FSYS_MINIX_NUM \
+ FSYS_TFTP_NUM)
#endif #endif
/* defines for the block filesystem info area */ /* defines for the block filesystem info area */

View file

@ -269,7 +269,11 @@ int
gunzip_test_header (void) gunzip_test_header (void)
{ {
unsigned char buf[10]; unsigned char buf[10];
int is_tftp = 0;
if (grub_strcmp (fsys_table[fsys_type].name, "tftp") == 0)
is_tftp = 1;
/* "compressed_file" is already reset to zero by this point */ /* "compressed_file" is already reset to zero by this point */
/* /*
@ -277,12 +281,13 @@ gunzip_test_header (void)
* (other than a real error with the disk) then we don't think it * (other than a real error with the disk) then we don't think it
* is a compressed file, and simply mark it as such. * is a compressed file, and simply mark it as such.
*/ */
if (no_decompression || grub_read (buf, 10) != 10 if (no_decompression
|| grub_read (buf, 10) != 10
|| ((*((unsigned short *) buf) != GZIP_HDR_LE) || ((*((unsigned short *) buf) != GZIP_HDR_LE)
& (*((unsigned short *) buf) != OLD_GZIP_HDR_LE))) && (*((unsigned short *) buf) != OLD_GZIP_HDR_LE)))
{ {
filepos = 0; filepos = 0;
return (!errnum); return ! errnum;
} }
/* /*
@ -290,23 +295,44 @@ gunzip_test_header (void)
* problem occurs from here on, then we have corrupt or otherwise * problem occurs from here on, then we have corrupt or otherwise
* bad data, and the error should be reported to the user. * bad data, and the error should be reported to the user.
*/ */
if (buf[2] != DEFLATED || (buf[3] & UNSUPP_FLAGS) if (buf[2] != DEFLATED
|| (buf[3] & UNSUPP_FLAGS)
|| ((buf[3] & EXTRA_FIELD) || ((buf[3] & EXTRA_FIELD)
&& (grub_read (buf, 2) != 2 || && (grub_read (buf, 2) != 2
bad_field (*((unsigned short *) buf)))) || bad_field (*((unsigned short *) buf))))
|| ((buf[3] & ORIG_NAME) && bad_field (-1)) || ((buf[3] & ORIG_NAME) && bad_field (-1))
|| ((buf[3] & COMMENT) && bad_field (-1)) || ((buf[3] & COMMENT) && bad_field (-1)))
|| ((gzip_data_offset = filepos), (filepos = filemax - 8),
(grub_read (buf, 8) != 8)))
{ {
if (!errnum) if (! errnum)
errnum = ERR_BAD_GZIP_HEADER; errnum = ERR_BAD_GZIP_HEADER;
return 0; return 0;
} }
gzip_crc = *((unsigned long *) buf); gzip_data_offset = filepos;
gzip_fsmax = gzip_filemax = *((unsigned long *) (buf + 4));
if (! is_tftp)
filepos = filemax - 8;
if (grub_read (buf, 8) != 8)
{
if (! errnum)
errnum = ERR_BAD_GZIP_HEADER;
return 0;
}
if (! is_tftp)
{
gzip_crc = *((unsigned long *) buf);
gzip_fsmax = gzip_filemax = *((unsigned long *) (buf + 4));
}
else
{
/* We don't have gzip_crc. */
gzip_fsmax = gzip_filemax = 16 * 1024 * 1024;
filepos = filemax;
}
initialize_tables (); initialize_tables ();

View file

@ -263,10 +263,12 @@ extern char *grub_scratch_mem;
#define memset grub_memset #define memset grub_memset
#define isspace grub_isspace #define isspace grub_isspace
#define printf grub_printf #define printf grub_printf
#define sprintf grub_sprintf
#undef putchar #undef putchar
#define putchar grub_putchar #define putchar grub_putchar
#define strncat grub_strncat #define strncat grub_strncat
#define strstr grub_strstr #define strstr grub_strstr
#define memcmp grub_memcmp
#define strcmp grub_strcmp #define strcmp grub_strcmp
#define tolower grub_tolower #define tolower grub_tolower
#define strlen grub_strlen #define strlen grub_strlen
@ -494,6 +496,7 @@ int get_code_end (void);
/* low-level timing info */ /* low-level timing info */
int getrtsecs (void); int getrtsecs (void);
int currticks (void);
/* Clear the screen. */ /* Clear the screen. */
void cls (void); void cls (void);
@ -585,12 +588,14 @@ int run_script (char *script, char *heap);
/* C library replacement functions with identical semantics. */ /* C library replacement functions with identical semantics. */
void grub_printf (const char *format,...); void grub_printf (const char *format,...);
int grub_sprintf (char *buffer, const char *format, ...);
int grub_tolower (int c); int grub_tolower (int c);
int grub_isspace (int c); int grub_isspace (int c);
int grub_strncat (char *s1, const char *s2, int n); int grub_strncat (char *s1, const char *s2, int n);
char *grub_memmove (char *to, const char *from, int len); char *grub_memmove (char *to, const char *from, int len);
void *grub_memset (void *start, int c, int len); void *grub_memset (void *start, int c, int len);
char *grub_strstr (const char *s1, const char *s2); char *grub_strstr (const char *s1, const char *s2);
int grub_memcmp (const char *s1, const char *s2, int n);
int grub_strcmp (const char *s1, const char *s2); int grub_strcmp (const char *s1, const char *s2);
int grub_strlen (const char *str); int grub_strlen (const char *str);

View file

@ -52,7 +52,7 @@ check minix_stage1_5 31744
# This limitation is arbitrary; If you want to make this larger, just # This limitation is arbitrary; If you want to make this larger, just
# modify Stage 1. # modify Stage 1.
check stage2 56320 check stage2 66560
# Success. # Success.
exit 0 exit 0