update the network support to etherboot-4.5.8.

This commit is contained in:
okuji 2000-04-22 01:17:09 +00:00
parent 26fef18cb8
commit 5ff25f9b8f
51 changed files with 5395 additions and 3479 deletions

143
ChangeLog
View file

@ -1,3 +1,146 @@
2000-04-22 OKUJI Yoshinori <okuji@gnu.org>
Update the network support to Etherboot 4.5.8.
* configure.in (--enable-3c590): New option.
(--enable-3c595): Likewise.
(--enable-depca): Likewise.
(--enable-lance): Likewise.
(--enable-ns8390): Likewise.
(--enable-ntulip): Likewise.
(--enable-lancepci): Removed.
(--enable-nepci): Likewise.
(--enable-otulip): Likewise.
(--enable-smc9000): The duplicated one is named to ...
(--enable-smc9000-scan): ... this. This was a typo, perhaps.
* netboot/Makefile.am (libdrivers_a_SOURCES): Removed
byteorder.h, if.h, netboot_config.h and netdevice.h, and added
cards.h.
(EXTRA_libdrivers_a_SOURCES): Removed ntulip.c and tulip.h, and
added 3c595.c, 3c595.h, depca.c, otulip.c and otulip.h.
(libdrivers_a_CFLAGS): Define FSYS_TFTP as 1 instead of empty.
(EXTRA_DIST): Removed ntulip.txt, and added cs89x0.txt and
tulip.txt.
(3c595_drivers): New variable.
(depca_drivers): Likewise.
(lance_drivers): Removed lancepci.o and added lance.o.
(ns8390_drivers): Removed nepci.o and added ns8390.o.
(ntulip_drivers): Deleted.
(otulip_drivers): New variable.
($(3c595_drivers)): New target.
($(depca_drivers)): Likewise.
($(ntulip_drivers)): Deleted.
($(otulip_drivers)): New target.
(3c590_o_CFLAGS): New variable.
(3c595_o_CFLAGS): Likewise.
(depca_o_CFLAGS): Likewise.
(lancepci_o_CFLAGS): Deleted.
(lance_o_CFLAGS): New variable.
(nepci_o_CFLAGS): Deleted.
(ns8390_o_CFLAGS): New variable.
(ntulip_o_CFLAGS): Deleted.
(otulip_o_CFLAGS): New variable.
* netboot/3c90x.c: Updated to Etherboot-4.5.8.
* netboot/3c90x.txt: Likewise.
* netboot/cs89x0.c: Likewise.
* netboot/cs89x0.h: Likewise.
* netboot/eepro100.c: Likewise.
* netboot/epic100.c: Likewise.
* netboot/epic100.h: Likewise.
* netboot/i82586.c: Likewise.
* netboot/lance.c: Likewise.
* netboot/linux-asm-io.h: Likewise.
* netboot/linux-asm-string.h: Likewise.
* netboot/nic.h: Likewise.
* netboot/ns8390.c: Likewise.
* netboot/ns8390.h: Likewise.
* netboot/pci.c: Likewise.
* netboot/pci.h: Likewise.
* netboot/rtl8139.c: Likewise.
* netboot/sk_g16.c: Likewise.
* netboot/sk_g16.h: Likewise.
* netboot/smc9000.c: Likewise.
* netboot/smc9000.h: Likewise.
* netboot/tiara.c: Likewise.
* netboot/tulip.c: Likewise.
* netboot/via-rhine.c: Likewise.
* netboot/config.c: Updated to Etherboot-4.5.8 and modified (see
below).
[GRUB] (print_config): Undefined.
(eth_probe) [GRUB]: If PROBED is true, do nothing. Otherwise,
clear NETWORK_READY and ARPTABLE, set ROM to ROM_INFO_LOCATION,
and set PROBED to 1 if succeeds.
* netboot/etherboot.h: Likewise,
(GRUB): New macro.
[GRUB]: Include <shared.h>.
[GRUB] (NO_DHCP_SUPPORT): Undefined.
[GRUB] (RELOC): Defined as zero.
[GRUB] (INTERNAL_BOOTP_DATA): Defined as one.
[GRUB] (USE_INTERNAL_BUFFER): Likewise.
[GRUB] (BACKOFF_LIMIT): Defined as 7.
[GRUB] (CTRL_C): New macro.
[GRUB] (print_network_configuration): Declared.
[GRUB] (ip_abort): Likewise.
[GRUB] (network_ready): Likewise.
* netboot/fsys_tftp.c: Don't include <netboot_config.h>.
(isocket): Renamed to ...
(iport): ... this.
(osocket): Renamed to ...
(oport): ... this.
(bcounter): New variable.
(buf_fill): When checking the block order, see BCOUNTER as well
as BLOCK.
Don't process a packet, if BLOCK minus PREVBLOCK is not 1,
instead of if BLOCK is less than or equal to PREVBLOCK.
Increment BCOUNTER after reseting RETRY.
(send_rrq): Clear BCOUNTER.
Call await_reply with AWAIT_QDRAIN.
* netboot/main.c: Don't include <netboot_config.h>.
(dhcpdiscover): Made const.
(dhcprequest): Likewise. Updated the contents.
(broadcast): Made const.
(udp_transmit): Copied.
(tftp): Likewise.
(bootp): Likewise.
(rarp): Likewise.
(await_reply): Likewise.
(decode_rfc1533): Likewise.
(rfc951_sleep): Likewise.
(cleanup_net): Likewise.
* netboot/misc.c (sleep): Copied.
(twiddle): Likewise.
(getdec): Likewise.
* netboot/osdep.h: Copied and modified (see below).
[GRUB] (ETHERBOOT32): Used the same definition as Linux and
FreeBSD.
[GRUB] (ntohl): Likewise.
[GRUB] (htonl): Likewise.
[GRUB] (ntohs): Likewise.
[GRUB] (htons): Likewise.
[GRUB] (swap32): Likewise.
[GRUB] (swap16): Likewise.
[GRUB]: Include "linux-asm-io.h".
* netboot/byteorder.h: Removed.
* netboot/if.h: Likewise.
* netboot/netboot_config.h: Likewise.
* netboot/netdevice.h: Likewise.
* netboot/ntulip.c: Likewise.
* netboot/ntulip.txt: Likewise.
* netboot/tulip.h: Likewise.
* netboot/3c595.c: New file. Copied from Etherboot-4.5.8.
* netboot/3c595.h: Likewise.
* netboot/cards.h: Likewise.
* netboot/cs89x0.txt: Likewise.
* netboot/depca.c: Likewise.
* netboot/otulip.c: Likewise.
* netboot/otulip.h: Likewise.
* netboot/tulip.txt: Likewise.
2000-02-29 Jochen Hoenicke <jochen@gnu.org>
* stage2/common.c (err_list): Added message for ERR_UNALIGNED.

2
NEWS
View file

@ -21,6 +21,8 @@ New in 0.5.95 - XXXX-XX-XX:
"grub-install" has the same effect as to the command "install".
* The configure script doesn't accept the option
`--disable-lba-support-bitmap-check' any longer. Use the option above.
* The network support is updated to Etherboot-4.5.8. So now we have
3Com59x and DEPCA drivers.
New in 0.5.94 - 2000-03-06:
* Stage 1 supports both the LBA mode and the CHS mode.

244
configure vendored
View file

@ -42,10 +42,16 @@ ac_help="$ac_help
--enable-3c509 enable 3Com509 driver"
ac_help="$ac_help
--enable-3c529 enable 3Com529 driver"
ac_help="$ac_help
--enable-3c590 enable 3Com590 driver"
ac_help="$ac_help
--enable-3c595 enable 3Com595 driver"
ac_help="$ac_help
--enable-3c90x enable 3Com90x driver"
ac_help="$ac_help
--enable-cs89x0 enable CS89x0 driver"
ac_help="$ac_help
--enable-depca enable DEPCA and EtherWORKS driver"
ac_help="$ac_help
--enable-eepro100 enable Etherexpress Pro/100 driver"
ac_help="$ac_help
@ -57,7 +63,7 @@ ac_help="$ac_help
ac_help="$ac_help
--enable-ni5210 enable Racal-Interlan NI5210 driver"
ac_help="$ac_help
--enable-lancepci enable Lance PCI PCNet/32 driver"
--enable-lance enable Lance PCI PCNet/32 driver"
ac_help="$ac_help
--enable-ne2100 enable Novell NE2100 driver"
ac_help="$ac_help
@ -67,11 +73,11 @@ ac_help="$ac_help
ac_help="$ac_help
--enable-ne enable NE1000/2000 ISA driver"
ac_help="$ac_help
--enable-nepci enable NE2000 PCI driver"
--enable-ns8390 enable NE2000 PCI driver"
ac_help="$ac_help
--enable-wd enable WD8003/8013, SMC8216/8416 driver"
ac_help="$ac_help
--enable-ntulip enable Tulip driver"
--enable-otulip enable old Tulip driver"
ac_help="$ac_help
--enable-rtl8139 enable Realtek 8139 driver"
ac_help="$ac_help
@ -81,7 +87,7 @@ ac_help="$ac_help
ac_help="$ac_help
--enable-tiara enable Tiara driver"
ac_help="$ac_help
--enable-tulip enable old Tulip driver"
--enable-tulip enable Tulip driver"
ac_help="$ac_help
--enable-via-rhine enable Rhine-I/II driver"
ac_help="$ac_help
@ -644,7 +650,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:648: checking for a BSD compatible install" >&5
echo "configure:654: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -697,7 +703,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
echo "configure:701: checking whether build environment is sane" >&5
echo "configure:707: checking whether build environment is sane" >&5
# Just in case
sleep 1
echo timestamp > conftestfile
@ -769,7 +775,7 @@ do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:773: checking for $ac_word" >&5
echo "configure:779: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -799,7 +805,7 @@ test -n "$AWK" && break
done
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
echo "configure:803: checking whether ${MAKE-make} sets \${MAKE}" >&5
echo "configure:809: checking whether ${MAKE-make} sets \${MAKE}" >&5
set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -934,7 +940,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
fi
echo $ac_n "checking host system type""... $ac_c" 1>&6
echo "configure:938: checking host system type" >&5
echo "configure:944: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@ -968,7 +974,7 @@ esac
#
echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6
echo "configure:972: checking whether to enable maintainer-specific portions of Makefiles" >&5
echo "configure:978: checking whether to enable maintainer-specific portions of Makefiles" >&5
# Check whether --enable-maintainer-mode or --disable-maintainer-mode was given.
if test "${enable_maintainer_mode+set}" = set; then
enableval="$enable_maintainer_mode"
@ -994,7 +1000,7 @@ if test "x$enable_maintainer_mode" = xyes; then
# Extract the first word of "perl", so it can be a program name with args.
set dummy perl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:998: checking for $ac_word" >&5
echo "configure:1004: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_PERL'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1041,7 +1047,7 @@ fi
#
echo $ac_n "checking build system type""... $ac_c" 1>&6
echo "configure:1045: checking build system type" >&5
echo "configure:1051: checking build system type" >&5
build_alias=$build
case "$build_alias" in
@ -1067,7 +1073,7 @@ fi
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1071: checking for $ac_word" >&5
echo "configure:1077: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1099,7 +1105,7 @@ fi
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1103: checking for $ac_word" >&5
echo "configure:1109: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1129,7 +1135,7 @@ if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1133: checking for $ac_word" >&5
echo "configure:1139: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1180,7 +1186,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1184: checking for $ac_word" >&5
echo "configure:1190: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1212,7 +1218,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
echo "configure:1216: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
echo "configure:1222: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@ -1223,12 +1229,12 @@ cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext << EOF
#line 1227 "configure"
#line 1233 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
if { (eval echo configure:1232: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@ -1254,12 +1260,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; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
echo "configure:1258: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "configure:1264: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
echo "configure:1263: checking whether we are using GNU C" >&5
echo "configure:1269: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1268,7 +1274,7 @@ else
yes;
#endif
EOF
if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:1272: \"$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:1278: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
@ -1287,7 +1293,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
echo "configure:1291: checking whether ${CC-cc} accepts -g" >&5
echo "configure:1297: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1320,7 +1326,7 @@ fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
echo "configure:1324: checking how to run the C preprocessor" >&5
echo "configure:1330: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@ -1335,13 +1341,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
#line 1339 "configure"
#line 1345 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1345: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1351: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@ -1352,13 +1358,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
#line 1356 "configure"
#line 1362 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1362: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1368: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@ -1369,13 +1375,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
#line 1373 "configure"
#line 1379 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:1379: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:1385: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@ -1408,7 +1414,7 @@ echo "$ac_t""$CPP" 1>&6
depcc="$CC"
depcpp="$CPP"
echo $ac_n "checking dependency style of $depcc""... $ac_c" 1>&6
echo "configure:1412: checking dependency style of $depcc" >&5
echo "configure:1418: checking dependency style of $depcc" >&5
if eval "test \"`echo '$''{'am_cv_CC_dependencies_compiler_type'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1464,7 +1470,7 @@ if test "x$with_binutils" != x; then
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1468: checking for $ac_word" >&5
echo "configure:1474: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1501,7 +1507,7 @@ else
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1505: checking for $ac_word" >&5
echo "configure:1511: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1541,7 +1547,7 @@ if test "x$ac_cv_prog_gcc" = xyes; then
STAGE1_CFLAGS="-O2"
GRUB_CFLAGS="-O2"
echo $ac_n "checking whether optimization for size works""... $ac_c" 1>&6
echo "configure:1545: checking whether optimization for size works" >&5
echo "configure:1551: checking whether optimization for size works" >&5
if eval "test \"`echo '$''{'size_flag'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1549,14 +1555,14 @@ else
saved_CFLAGS=$CFLAGS
CFLAGS="-Os -g"
cat > conftest.$ac_ext <<EOF
#line 1553 "configure"
#line 1559 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
if { (eval echo configure:1560: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:1566: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
size_flag=yes
else
@ -1590,7 +1596,7 @@ if test "x$with_binutils" != x; then
# Extract the first word of "objcopy", so it can be a program name with args.
set dummy objcopy; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1594: checking for $ac_word" >&5
echo "configure:1600: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_OBJCOPY'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1626,7 +1632,7 @@ else
# 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
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:1630: checking for $ac_word" >&5
echo "configure:1636: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_OBJCOPY'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1660,7 +1666,7 @@ fi
# Defined in acinclude.m4.
echo $ac_n "checking if C symbols get an underscore after compilation""... $ac_c" 1>&6
echo "configure:1664: checking if C symbols get an underscore after compilation" >&5
echo "configure:1670: checking if C symbols get an underscore after compilation" >&5
if eval "test \"`echo '$''{'grub_cv_asm_uscore'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1673,7 +1679,7 @@ func (int *list)
}
EOF
if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'; { (eval echo configure:1677: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.s; then
if { ac_try='${CC-cc} ${CFLAGS} -S conftest.c'; { (eval echo configure:1683: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.s; then
true
else
{ echo "configure: error: ${CC-cc} failed to produce assembly code" 1>&2; exit 1; }
@ -1699,7 +1705,7 @@ fi
echo "$ac_t""$grub_cv_asm_uscore" 1>&6
echo $ac_n "checking whether ${OBJCOPY} works for absolute addresses""... $ac_c" 1>&6
echo "configure:1703: checking whether ${OBJCOPY} works for absolute addresses" >&5
echo "configure:1709: checking whether ${OBJCOPY} works for absolute addresses" >&5
if eval "test \"`echo '$''{'grub_cv_prog_objcopy_absolute'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1711,21 +1717,21 @@ cmain (void)
}
EOF
if { (eval echo configure:1715: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then :
if { (eval echo configure:1721: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.o; then :
else
{ echo "configure: error: ${CC-cc} cannot compile C source code" 1>&2; exit 1; }
fi
grub_cv_prog_objcopy_absolute=yes
for link_addr in 2000 8000 7C00; do
if { ac_try='${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec'; { (eval echo configure:1721: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then :
if { ac_try='${CC-cc} ${CFLAGS} -nostdlib -Wl,-N -Wl,-Ttext -Wl,$link_addr conftest.o -o conftest.exec'; { (eval echo configure:1727: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then :
else
{ echo "configure: error: ${CC-cc} cannot link at address $link_addr" 1>&2; exit 1; }
fi
if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'; { (eval echo configure:1725: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then :
if { ac_try='${OBJCOPY-objcopy} -O binary conftest.exec conftest'; { (eval echo configure:1731: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then :
else
{ echo "configure: error: ${OBJCOPY-objcopy} cannot create binary files" 1>&2; exit 1; }
fi
if test ! -f conftest.old || { ac_try='cmp -s conftest.old conftest'; { (eval echo configure:1729: \"$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:1735: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then
mv -f conftest conftest.old
else
grub_cv_prog_objcopy_absolute=no
@ -1742,7 +1748,7 @@ fi
echo $ac_n "checking whether addr32 must be in the same line as the instruction""... $ac_c" 1>&6
echo "configure:1746: checking whether addr32 must be in the same line as the instruction" >&5
echo "configure:1752: checking whether addr32 must be in the same line as the instruction" >&5
if eval "test \"`echo '$''{'grub_cv_asm_prefix_requirement'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1751,7 +1757,7 @@ else
l1: addr32 movb %al, l1
EOF
if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1755: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then
if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1761: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then
grub_cv_asm_prefix_requirement=yes
else
grub_cv_asm_prefix_requirement=no
@ -1783,7 +1789,7 @@ echo "$ac_t""$grub_cv_asm_prefix_requirement" 1>&6
echo $ac_n "checking for .code16 addr32 assembler support""... $ac_c" 1>&6
echo "configure:1787: checking for .code16 addr32 assembler support" >&5
echo "configure:1793: checking for .code16 addr32 assembler support" >&5
if eval "test \"`echo '$''{'grub_cv_asm_addr32'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -1798,7 +1804,7 @@ else
sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s
fi
if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1802: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then
if { ac_try='${CC-cc} ${CFLAGS} -c conftest.s'; { (eval echo configure:1808: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } && test -s conftest.o; then
grub_cv_asm_addr32=yes
else
grub_cv_asm_addr32=no
@ -1815,19 +1821,19 @@ fi
echo $ac_n "checking if start is defined by the compiler""... $ac_c" 1>&6
echo "configure:1819: checking if start is defined by the compiler" >&5
echo "configure:1825: checking if start is defined by the compiler" >&5
if eval "test \"`echo '$''{'grub_cv_check_start_symbol'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1824 "configure"
#line 1830 "configure"
#include "confdefs.h"
int main() {
asm ("incl start")
; return 0; }
EOF
if { (eval echo configure:1831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1837: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
grub_cv_check_start_symbol=yes
else
@ -1851,19 +1857,19 @@ echo "$ac_t""$grub_cv_check_start_symbol" 1>&6
echo $ac_n "checking if _start is defined by the compiler""... $ac_c" 1>&6
echo "configure:1855: checking if _start is defined by the compiler" >&5
echo "configure:1861: checking if _start is defined by the compiler" >&5
if eval "test \"`echo '$''{'grub_cv_check_uscore_start_symbol'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1860 "configure"
#line 1866 "configure"
#include "confdefs.h"
int main() {
asm ("incl _start")
; return 0; }
EOF
if { (eval echo configure:1867: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1873: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
grub_cv_check_uscore_start_symbol=yes
else
@ -1892,19 +1898,19 @@ fi
echo $ac_n "checking if __bss_start is defined by the compiler""... $ac_c" 1>&6
echo "configure:1896: checking if __bss_start is defined by the compiler" >&5
echo "configure:1902: checking if __bss_start is defined by the compiler" >&5
if eval "test \"`echo '$''{'grub_cv_check_uscore_uscore_bss_start_symbol'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1901 "configure"
#line 1907 "configure"
#include "confdefs.h"
int main() {
asm ("incl __bss_start")
; return 0; }
EOF
if { (eval echo configure:1908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1914: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
grub_cv_check_uscore_uscore_bss_start_symbol=yes
else
@ -1928,19 +1934,19 @@ echo "$ac_t""$grub_cv_check_uscore_uscore_bss_start_symbol" 1>&6
echo $ac_n "checking if _edata is defined by the compiler""... $ac_c" 1>&6
echo "configure:1932: checking if _edata is defined by the compiler" >&5
echo "configure:1938: checking if _edata is defined by the compiler" >&5
if eval "test \"`echo '$''{'grub_cv_check_uscore_edata_symbol'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1937 "configure"
#line 1943 "configure"
#include "confdefs.h"
int main() {
asm ("incl _edata")
; return 0; }
EOF
if { (eval echo configure:1944: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1950: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
grub_cv_check_uscore_edata_symbol=yes
else
@ -1964,19 +1970,19 @@ echo "$ac_t""$grub_cv_check_uscore_edata_symbol" 1>&6
echo $ac_n "checking if edata is defined by the compiler""... $ac_c" 1>&6
echo "configure:1968: checking if edata is defined by the compiler" >&5
echo "configure:1974: checking if edata is defined by the compiler" >&5
if eval "test \"`echo '$''{'grub_cv_check_edata_symbol'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 1973 "configure"
#line 1979 "configure"
#include "confdefs.h"
int main() {
asm ("incl edata")
; return 0; }
EOF
if { (eval echo configure:1980: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:1986: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
grub_cv_check_edata_symbol=yes
else
@ -2006,19 +2012,19 @@ fi
echo $ac_n "checking if end is defined by the compiler""... $ac_c" 1>&6
echo "configure:2010: checking if end is defined by the compiler" >&5
echo "configure:2016: checking if end is defined by the compiler" >&5
if eval "test \"`echo '$''{'grub_cv_check_end_symbol'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2015 "configure"
#line 2021 "configure"
#include "confdefs.h"
int main() {
asm ("incl end")
; return 0; }
EOF
if { (eval echo configure:2022: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2028: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
grub_cv_check_end_symbol=yes
else
@ -2042,19 +2048,19 @@ echo "$ac_t""$grub_cv_check_end_symbol" 1>&6
echo $ac_n "checking if _end is defined by the compiler""... $ac_c" 1>&6
echo "configure:2046: checking if _end is defined by the compiler" >&5
echo "configure:2052: checking if _end is defined by the compiler" >&5
if eval "test \"`echo '$''{'grub_cv_check_uscore_end_symbol'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2051 "configure"
#line 2057 "configure"
#include "confdefs.h"
int main() {
asm ("incl _end")
; return 0; }
EOF
if { (eval echo configure:2058: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
grub_cv_check_uscore_end_symbol=yes
else
@ -2092,7 +2098,7 @@ fi
# Get the filename or the whole disk and open it.
# Known to work on NetBSD.
echo $ac_n "checking for opendisk in -lutil""... $ac_c" 1>&6
echo "configure:2096: checking for opendisk in -lutil" >&5
echo "configure:2102: checking for opendisk in -lutil" >&5
ac_lib_var=`echo util'_'opendisk | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -2100,7 +2106,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lutil $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2104 "configure"
#line 2110 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@ -2111,7 +2117,7 @@ int main() {
opendisk()
; return 0; }
EOF
if { (eval echo configure:2115: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -2139,7 +2145,7 @@ fi
# Unless the user specify --without-curses, check for curses.
if test "x$with_curses" != "xno"; then
echo $ac_n "checking for wgetch in -lncurses""... $ac_c" 1>&6
echo "configure:2143: checking for wgetch in -lncurses" >&5
echo "configure:2149: checking for wgetch in -lncurses" >&5
ac_lib_var=`echo ncurses'_'wgetch | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -2147,7 +2153,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lncurses $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2151 "configure"
#line 2157 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@ -2158,7 +2164,7 @@ int main() {
wgetch()
; return 0; }
EOF
if { (eval echo configure:2162: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -2181,7 +2187,7 @@ EOF
else
echo "$ac_t""no" 1>&6
echo $ac_n "checking for wgetch in -lcurses""... $ac_c" 1>&6
echo "configure:2185: checking for wgetch in -lcurses" >&5
echo "configure:2191: checking for wgetch in -lcurses" >&5
ac_lib_var=`echo curses'_'wgetch | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@ -2189,7 +2195,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lcurses $LIBS"
cat > conftest.$ac_ext <<EOF
#line 2193 "configure"
#line 2199 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@ -2200,7 +2206,7 @@ int main() {
wgetch()
; return 0; }
EOF
if { (eval echo configure:2204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:2210: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@ -2235,17 +2241,17 @@ for ac_hdr in string.h strings.h ncurses/curses.h ncurses.h curses.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2239: checking for $ac_hdr" >&5
echo "configure:2245: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2244 "configure"
#line 2250 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2249: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2255: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@ -2385,6 +2391,27 @@ if test "x$enable_3c529" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c529.o"
fi
# Check whether --enable-3c590 or --disable-3c590 was given.
if test "${enable_3c590+set}" = set; then
enableval="$enable_3c590"
:
fi
if test "x$enable_3c590" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C590=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c590.o"
fi
# Check whether --enable-3c595 or --disable-3c595 was given.
if test "${enable_3c595+set}" = set; then
enableval="$enable_3c595"
:
fi
if test "x$enable_3c595" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C595=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c595.o"
fi
# Check whether --enable-3c90x or --disable-3c90x was given.
if test "${enable_3c90x+set}" = set; then
@ -2408,6 +2435,17 @@ if test "x$enable_cs89x0" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS cs89x0.o"
fi
# Check whether --enable-depca or --disable-depca was given.
if test "${enable_depca+set}" = set; then
enableval="$enable_depca"
:
fi
if test "x$enable_depca" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_DEPCA=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS depca.o"
fi
# Check whether --enable-eepro100 or --disable-eepro100 was given.
if test "${enable_eepro100+set}" = set; then
enableval="$enable_eepro100"
@ -2463,15 +2501,15 @@ if test "x$enable_ni5210" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ni5210.o"
fi
# Check whether --enable-lancepci or --disable-lancepci was given.
if test "${enable_lancepci+set}" = set; then
enableval="$enable_lancepci"
# Check whether --enable-lance or --disable-lance was given.
if test "${enable_lance+set}" = set; then
enableval="$enable_lance"
:
fi
if test "x$enable_lancepci" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_LANCEPCI=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS lancepci.o"
if test "x$enable_lance" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_LANCE=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS lance.o"
fi
# Check whether --enable-ne2100 or --disable-ne2100 was given.
@ -2518,15 +2556,15 @@ if test "x$enable_ne" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ne.o"
fi
# Check whether --enable-nepci or --disable-nepci was given.
if test "${enable_nepci+set}" = set; then
enableval="$enable_nepci"
# Check whether --enable-ns8390 or --disable-ns8390 was given.
if test "${enable_ns8390+set}" = set; then
enableval="$enable_ns8390"
:
fi
if test "x$enable_nepci" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NEPCI=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS nepci.o"
if test "x$enable_ns8390" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NS8390=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ns8390.o"
fi
# Check whether --enable-wd or --disable-wd was given.
@ -2540,15 +2578,15 @@ if test "x$enable_wd" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS wd.o"
fi
# Check whether --enable-ntulip or --disable-ntulip was given.
if test "${enable_ntulip+set}" = set; then
enableval="$enable_ntulip"
# Check whether --enable-otulip or --disable-otulip was given.
if test "${enable_otulip+set}" = set; then
enableval="$enable_otulip"
:
fi
if test "x$enable_ntulip" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NTULIP=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ntulip.o"
if test "x$enable_otulip" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_OTULIP=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS otulip.o"
fi
# Check whether --enable-rtl8139 or --disable-rtl8139 was given.
@ -2670,9 +2708,9 @@ if test "x$enable_compex_rl2000_fix" = xyes; then
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCOMPEX_RL2000_FIX=1"
fi
# Check whether --enable-smc9000 or --disable-smc9000 was given.
if test "${enable_smc9000+set}" = set; then
enableval="$enable_smc9000"
# Check whether --enable-smc9000-scan or --disable-smc9000-scan was given.
if test "${enable_smc9000_scan+set}" = set; then
enableval="$enable_smc9000_scan"
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DSMC9000_SCAN=$enable_smc9000_scan"
fi

View file

@ -1,5 +1,5 @@
dnl Configure script for GRUB.
dnl Copyright 1999 Free Software Foundation, Inc.
dnl Copyright 1999,2000 Free Software Foundation, Inc.
dnl Permission to use, copy, modify and distribute this software and its
dnl documentation is hereby granted, provided that both the copyright
@ -244,12 +244,19 @@ if test "x$enable_3c529" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c529.o"
fi
dnl AC_ARG_ENABLE(3c59x,
dnl [ --enable-3c59x enable 3Com59x driver])
dnl if test "x$enable_3c59x" = xyes; then
dnl NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C59x=1"
dnl NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c59x.o"
dnl fi
AC_ARG_ENABLE(3c590,
[ --enable-3c590 enable 3Com590 driver])
if test "x$enable_3c590" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C590=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c590.o"
fi
AC_ARG_ENABLE(3c595,
[ --enable-3c595 enable 3Com595 driver])
if test "x$enable_3c595" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_3C595=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c595.o"
fi
AC_ARG_ENABLE(3c90x,
[ --enable-3c90x enable 3Com90x driver])
@ -265,6 +272,13 @@ if test "x$enable_cs89x0" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS cs89x0.o"
fi
AC_ARG_ENABLE(depca,
[ --enable-depca enable DEPCA and EtherWORKS driver])
if test "x$enable_depca" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_DEPCA=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS depca.o"
fi
AC_ARG_ENABLE(eepro100,
[ --enable-eepro100 enable Etherexpress Pro/100 driver])
if test "x$enable_eepro100" = xyes; then
@ -300,11 +314,11 @@ if test "x$enable_ni5210" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ni5210.o"
fi
AC_ARG_ENABLE(lancepci,
[ --enable-lancepci enable Lance PCI PCNet/32 driver])
if test "x$enable_lancepci" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_LANCEPCI=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS lancepci.o"
AC_ARG_ENABLE(lance,
[ --enable-lance enable Lance PCI PCNet/32 driver])
if test "x$enable_lance" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_LANCE=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS lance.o"
fi
AC_ARG_ENABLE(ne2100,
@ -335,11 +349,11 @@ if test "x$enable_ne" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ne.o"
fi
AC_ARG_ENABLE(nepci,
[ --enable-nepci enable NE2000 PCI driver])
if test "x$enable_nepci" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NEPCI=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS nepci.o"
AC_ARG_ENABLE(ns8390,
[ --enable-ns8390 enable NE2000 PCI driver])
if test "x$enable_ns8390" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NS8390=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ns8390.o"
fi
AC_ARG_ENABLE(wd,
@ -349,11 +363,11 @@ if test "x$enable_wd" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS wd.o"
fi
AC_ARG_ENABLE(ntulip,
[ --enable-ntulip enable Tulip driver])
if test "x$enable_ntulip" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NTULIP=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ntulip.o"
AC_ARG_ENABLE(otulip,
[ --enable-otulip enable old Tulip driver])
if test "x$enable_otulip" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_OTULIP=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS otulip.o"
fi
AC_ARG_ENABLE(rtl8139,
@ -385,7 +399,7 @@ if test "x$enable_tiara" = xyes; then
fi
AC_ARG_ENABLE(tulip,
[ --enable-tulip enable old Tulip driver])
[ --enable-tulip enable Tulip driver])
if test "x$enable_tulip" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_TULIP=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS tulip.o"
@ -430,7 +444,7 @@ if test "x$enable_compex_rl2000_fix" = xyes; then
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCOMPEX_RL2000_FIX=1"
fi
AC_ARG_ENABLE(smc9000,
AC_ARG_ENABLE(smc9000-scan,
[ --enable-smc9000-scan=LIST
probe for SMC9000 I/O addresses using LIST],
[NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DSMC9000_SCAN=$enable_smc9000_scan"])

535
netboot/3c595.c Normal file
View file

@ -0,0 +1,535 @@
/*
* 3c595.c -- 3COM 3C595 Fast Etherlink III PCI driver for etherboot
*
* Copyright (C) 2000 Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
* All rights reserved.
* Mar. 14, 2000
*
* 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.
*
* This code is based on Martin Renters' etherboot-4.4.3 3c509.c and
* Herb Peyerl's FreeBSD 3.4-RELEASE if_vx.c driver.
*
* Copyright (C) 1993-1994, David Greenman, Martin Renters.
* Copyright (C) 1993-1995, Andres Vega Garcia.
* Copyright (C) 1995, Serge Babkin.
*
* Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca>
*
*/
/* #define EDEBUG */
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#include "3c595.h"
static unsigned char eth_vendor, eth_flags, eth_laar;
static unsigned short eth_nic_base, eth_asic_base;
static unsigned short vx_connector, vx_connectors;
static struct connector_entry {
int bit;
char *name;
} conn_tab[VX_CONNECTORS] = {
#define CONNECTOR_UTP 0
{ 0x08, "utp"},
#define CONNECTOR_AUI 1
{ 0x20, "aui"},
/* dummy */
{ 0, "???"},
#define CONNECTOR_BNC 3
{ 0x10, "bnc"},
#define CONNECTOR_TX 4
{ 0x02, "tx"},
#define CONNECTOR_FX 5
{ 0x04, "fx"},
#define CONNECTOR_MII 6
{ 0x40, "mii"},
{ 0, "???"}
};
static void vxgetlink(void);
static void vxsetlink(void);
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 t595_reset(struct nic *nic)
{
int i, j;
/***********************************************************
Reset 3Com 595 card
*************************************************************/
/* stop card */
outw(RX_DISABLE, BASE + VX_COMMAND);
outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
VX_BUSY_WAIT;
outw(TX_DISABLE, BASE + VX_COMMAND);
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
DELAY(8000);
outw(RX_RESET, BASE + VX_COMMAND);
VX_BUSY_WAIT;
outw(TX_RESET, BASE + VX_COMMAND);
VX_BUSY_WAIT;
outw(C_INTR_LATCH, BASE + VX_COMMAND);
outw(SET_RD_0_MASK, BASE + VX_COMMAND);
outw(SET_INTR_MASK, BASE + VX_COMMAND);
outw(SET_RX_FILTER, BASE + VX_COMMAND);
/*
* initialize card
*/
VX_BUSY_WAIT;
GO_WINDOW(0);
/* Disable the card */
/* outw(0, BASE + VX_W0_CONFIG_CTRL); */
/* Configure IRQ to none */
/* outw(SET_IRQ(0), BASE + VX_W0_RESOURCE_CFG); */
/* Enable the card */
/* outw(ENABLE_DRQ_IRQ, BASE + VX_W0_CONFIG_CTRL); */
GO_WINDOW(2);
/* Reload the ether_addr. */
for (i = 0; i < ETHER_ADDR_SIZE; i++)
outb(nic->node_addr[i], BASE + VX_W2_ADDR_0 + i);
outw(RX_RESET, BASE + VX_COMMAND);
VX_BUSY_WAIT;
outw(TX_RESET, BASE + VX_COMMAND);
VX_BUSY_WAIT;
/* Window 1 is operating window */
GO_WINDOW(1);
for (i = 0; i < 31; i++)
inb(BASE + VX_W1_TX_STATUS);
outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE |
S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND);
/*
* Attempt to get rid of any stray interrupts that occured during
* configuration. On the i386 this isn't possible because one may
* already be queued. However, a single stray interrupt is
* unimportant.
*/
outw(ACK_INTR | 0xff, BASE + VX_COMMAND);
outw(SET_RX_FILTER | FIL_INDIVIDUAL |
FIL_BRDCST, BASE + VX_COMMAND);
vxsetlink();
/*{
int i,j;
i = CONNECTOR_TX;
GO_WINDOW(3);
j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
outl(BASE + VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS));
GO_WINDOW(4);
outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
GO_WINDOW(1);
}*/
/* start tranciever and receiver */
outw(RX_ENABLE, BASE + VX_COMMAND);
outw(TX_ENABLE, BASE + VX_COMMAND);
}
/**************************************************************************
ETH_TRANSMIT - Transmit a frame
***************************************************************************/
static char padmap[] = {
0, 3, 2, 1};
static void t595_transmit(
struct nic *nic,
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
const char *p) /* Packet */
{
register unsigned int len;
int pad;
int status;
#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 + VX_W1_TX_STATUS) )& TXS_COMPLETE ) {
if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
outw(TX_RESET, BASE + VX_COMMAND);
outw(TX_ENABLE, BASE + VX_COMMAND);
}
outb(0x0, BASE + VX_W1_TX_STATUS);
}
while (inw(BASE + VX_W1_FREE_TX) < len + pad + 4) {
/* no room in FIFO */
}
outw(len, BASE + VX_W1_TX_PIO_WR_1);
outw(0x0, BASE + VX_W1_TX_PIO_WR_1); /* Second dword meaningless */
/* write packet */
outsw(BASE + VX_W1_TX_PIO_WR_1, d, ETHER_ADDR_SIZE/2);
outsw(BASE + VX_W1_TX_PIO_WR_1, nic->node_addr, ETHER_ADDR_SIZE/2);
outw(t, BASE + VX_W1_TX_PIO_WR_1);
outsw(BASE + VX_W1_TX_PIO_WR_1, p, s / 2);
if (s & 1)
outb(*(p+s - 1), BASE + VX_W1_TX_PIO_WR_1);
while (pad--)
outb(0, BASE + VX_W1_TX_PIO_WR_1); /* Padding */
/* timeout after sending */
DELAY(1000);
}
/**************************************************************************
ETH_POLL - Wait for a frame
***************************************************************************/
static int t595_poll(struct nic *nic)
{
/* common variables */
unsigned short type = 0; /* used by EDEBUG */
/* variables for 3C509 */
short status, cst;
register short rx_fifo;
cst=inw(BASE + VX_STATUS);
#ifdef EDEBUG
if(cst & 0x1FFF)
printf("-%x-",cst);
#endif
if( (cst & S_RX_COMPLETE)==0 ) {
/* acknowledge everything */
outw(ACK_INTR | cst, BASE + VX_COMMAND);
outw(C_INTR_LATCH, BASE + VX_COMMAND);
return 0;
}
status = inw(BASE + VX_W1_RX_STATUS);
#ifdef EDEBUG
printf("*%x*",status);
#endif
if (status & ERR_RX) {
outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
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 + VX_W1_RX_PIO_RD_1, nic->packet, rx_fifo / 2);
if(rx_fifo & 1)
nic->packet[rx_fifo-1]=inb(BASE + VX_W1_RX_PIO_RD_1);
nic->packetlen=rx_fifo;
while(1) {
status = inw(BASE + VX_W1_RX_STATUS);
#ifdef EDEBUG
printf("*%x*",status);
#endif
rx_fifo = status & RX_BYTES_MASK;
if(rx_fifo>0) {
insw(BASE + VX_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 + VX_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(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND);
while (inw(BASE + VX_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(BASE) && i < MAX_EEPROMBUSY; i++)
DELAY(1000);
if (i >= MAX_EEPROMBUSY) {
/* printf("3c509: eeprom failed to come ready.\n"); */
printf("3c595: eeprom is busy.\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(EEPROM_CMD_RD | offset, BASE + VX_W0_EEPROM_COMMAND);
if (!eeprom_rdy())
return (0xffff);
return (inw(BASE + VX_W0_EEPROM_DATA));
}
static void
vxgetlink(void)
{
int n, k;
GO_WINDOW(3);
vx_connectors = inw(BASE + VX_W3_RESET_OPT) & 0x7f;
for (n = 0, k = 0; k < VX_CONNECTORS; k++) {
if (vx_connectors & conn_tab[k].bit) {
if (n > 0) {
printf("/");
}
printf(conn_tab[k].name);
n++;
}
}
if (vx_connectors == 0) {
printf("no connectors!");
return;
}
GO_WINDOW(3);
vx_connector = (inl(BASE + VX_W3_INTERNAL_CFG)
& INTERNAL_CONNECTOR_MASK)
>> INTERNAL_CONNECTOR_BITS;
if (vx_connector & 0x10) {
vx_connector &= 0x0f;
printf("[*%s*]", conn_tab[vx_connector].name);
printf(": disable 'auto select' with DOS util!");
} else {
printf("[*%s*]", conn_tab[vx_connector].name);
}
}
static void
vxsetlink(void)
{
int i, j, k;
char *reason, *warning;
static short prev_flags;
static char prev_conn = -1;
if (prev_conn == -1) {
prev_conn = vx_connector;
}
i = vx_connector; /* default in EEPROM */
reason = "default";
warning = 0;
if ((vx_connectors & conn_tab[vx_connector].bit) == 0) {
warning = "strange connector type in EEPROM.";
reason = "forced";
i = CONNECTOR_UTP;
}
if (warning != 0) {
printf("warning: %s\n", warning);
}
printf("selected %s. (%s)\n", conn_tab[i].name, reason);
/* Set the selected connector. */
GO_WINDOW(3);
j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK;
outl(j | (i <<INTERNAL_CONNECTOR_BITS), BASE + VX_W3_INTERNAL_CFG);
/* First, disable all. */
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
DELAY(8000);
GO_WINDOW(4);
outw(0, BASE + VX_W4_MEDIA_TYPE);
/* Second, enable the selected one. */
switch(i) {
case CONNECTOR_UTP:
GO_WINDOW(4);
outw(ENABLE_UTP, BASE + VX_W4_MEDIA_TYPE);
break;
case CONNECTOR_BNC:
outw(START_TRANSCEIVER,BASE + VX_COMMAND);
DELAY(8000);
break;
case CONNECTOR_TX:
case CONNECTOR_FX:
GO_WINDOW(4);
outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE);
break;
default: /* AUI and MII fall here */
break;
}
GO_WINDOW(1);
}
static void t595_disable(struct nic *nic)
{
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
DELAY(8000);
GO_WINDOW(4);
outw(0, BASE + VX_W4_MEDIA_TYPE);
GO_WINDOW(1);
}
/**************************************************************************
ETH_PROBE - Look for an adapter
***************************************************************************/
struct nic *t595_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_device *pci)
{
int i;
unsigned short *p;
if (probeaddrs == 0 || probeaddrs[0] == 0)
return 0;
/* eth_nic_base = probeaddrs[0] & ~3; */
eth_nic_base = pci->ioaddr;
GO_WINDOW(0);
outw(GLOBAL_RESET, BASE + VX_COMMAND);
VX_BUSY_WAIT;
vxgetlink();
/*
printf("\nEEPROM:");
for (i = 0; i < (EEPROMSIZE/2); i++) {
printf("%x:", get_e(i));
}
printf("\n");
*/
/*
* Read the station address from the eeprom
*/
p = (unsigned short *) nic->node_addr;
for (i = 0; i < 3; i++) {
GO_WINDOW(0);
p[i] = htons(get_e(EEPROM_OEM_ADDR_0 + i));
GO_WINDOW(2);
outw(ntohs(p[i]), BASE + VX_W2_ADDR_0 + (i * 2));
}
printf("Ethernet address: ");
for(i=0; i<5; i++) {
printf("%b:",nic->node_addr[i]);
}
printf("%b\n",nic->node_addr[i]);
t595_reset(nic);
nic->reset = t595_reset;
nic->poll = t595_poll;
nic->transmit = t595_transmit;
nic->disable = t595_disable;
return nic;
}
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

435
netboot/3c595.h Normal file
View file

@ -0,0 +1,435 @@
/*
* 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 without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
October 2, 1994
Modified by: Andres Vega Garcia
INRIA - Sophia Antipolis, France
e-mail: avega@sophia.inria.fr
finger: avega@pax.inria.fr
*/
/*
* Created from if_epreg.h by Fred Gray (fgray@rice.edu) to support the
* 3c590 family.
*/
/*
* Modified by Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp>
* for etherboot
* Mar. 14, 2000
*/
/*
* 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 VX_LAST_TAG 0xd7
#define VX_MAX_BOARDS 16
#define VX_ID_PORT 0x100
/*
* some macros to acces long named fields
*/
#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)
/*
* Some short functions, worth to let them be a macro
*/
/**************************************************************************
* *
* These define the EEPROM data structure. They are used in the probe
* function to verify the existence 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 */
#define EEPROM_OEM_ADDR_0 0xa /* Word */
#define EEPROM_OEM_ADDR_1 0xb /* Word */
#define EEPROM_OEM_ADDR_2 0xc /* Word */
#define EEPROM_SOFT_INFO_2 0xf /* Software information 2 */
#define NO_RX_OVN_ANOMALY (1<<5)
/**************************************************************************
* *
* 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 VX_COMMAND 0x0e /* Write. BASE+0x0e is always a
* command reg. */
#define VX_STATUS 0x0e /* Read. BASE+0x0e is always status
* reg. */
#define VX_WINDOW 0x0f /* Read. BASE+0x0f is always window
* reg. */
/*
* Window 0 registers. Setup.
*/
/* Write */
#define VX_W0_EEPROM_DATA 0x0c
#define VX_W0_EEPROM_COMMAND 0x0a
#define VX_W0_RESOURCE_CFG 0x08
#define VX_W0_ADDRESS_CFG 0x06
#define VX_W0_CONFIG_CTRL 0x04
/* Read */
#define VX_W0_PRODUCT_ID 0x02
#define VX_W0_MFG_ID 0x00
/*
* Window 1 registers. Operating Set.
*/
/* Write */
#define VX_W1_TX_PIO_WR_2 0x02
#define VX_W1_TX_PIO_WR_1 0x00
/* Read */
#define VX_W1_FREE_TX 0x0c
#define VX_W1_TX_STATUS 0x0b /* byte */
#define VX_W1_TIMER 0x0a /* byte */
#define VX_W1_RX_STATUS 0x08
#define VX_W1_RX_PIO_RD_2 0x02
#define VX_W1_RX_PIO_RD_1 0x00
/*
* Window 2 registers. Station Address Setup/Read
*/
/* Read/Write */
#define VX_W2_ADDR_5 0x05
#define VX_W2_ADDR_4 0x04
#define VX_W2_ADDR_3 0x03
#define VX_W2_ADDR_2 0x02
#define VX_W2_ADDR_1 0x01
#define VX_W2_ADDR_0 0x00
/*
* Window 3 registers. FIFO Management.
*/
/* Read */
#define VX_W3_INTERNAL_CFG 0x00
#define VX_W3_RESET_OPT 0x08
#define VX_W3_FREE_TX 0x0c
#define VX_W3_FREE_RX 0x0a
/*
* Window 4 registers. Diagnostics.
*/
/* Read/Write */
#define VX_W4_MEDIA_TYPE 0x0a
#define VX_W4_CTRLR_STATUS 0x08
#define VX_W4_NET_DIAG 0x06
#define VX_W4_FIFO_DIAG 0x04
#define VX_W4_HOST_DIAG 0x02
#define VX_W4_TX_DIAG 0x00
/*
* Window 5 Registers. Results and Internal status.
*/
/* Read */
#define VX_W5_READ_0_MASK 0x0c
#define VX_W5_INTR_MASK 0x0a
#define VX_W5_RX_FILTER 0x08
#define VX_W5_RX_EARLY_THRESH 0x06
#define VX_W5_TX_AVAIL_THRESH 0x02
#define VX_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 (unsigned short) 0x0000 /* Wait at least 1ms
* after issuing */
#define WINDOW_SELECT (unsigned short) (0x1<<11)
#define START_TRANSCEIVER (unsigned 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 (unsigned short) (0x3<<11) /* state disabled on
* power-up */
#define RX_ENABLE (unsigned short) (0x4<<11)
#define RX_RESET (unsigned short) (0x5<<11)
#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11)
#define TX_ENABLE (unsigned short) (0x9<<11)
#define TX_DISABLE (unsigned short) (0xa<<11)
#define TX_RESET (unsigned short) (0xb<<11)
#define REQ_INTR (unsigned short) (0xc<<11)
/*
* The following C_* acknowledge the various interrupts. Some of them don't
* do anything. See the manual.
*/
#define ACK_INTR (unsigned short) (0x6800)
# define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1)
# define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2)
# define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4)
# define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8)
# define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10)
# define C_RX_EARLY (unsigned short) (ACK_INTR|0x20)
# define C_INT_RQD (unsigned short) (ACK_INTR|0x40)
# define C_UPD_STATS (unsigned short) (ACK_INTR|0x80)
#define SET_INTR_MASK (unsigned short) (0xe<<11)
#define SET_RD_0_MASK (unsigned short) (0xf<<11)
#define SET_RX_FILTER (unsigned short) (0x10<<11)
# define FIL_INDIVIDUAL (unsigned short) (0x1)
# define FIL_MULTICAST (unsigned short) (0x02)
# define FIL_BRDCST (unsigned short) (0x04)
# define FIL_PROMISC (unsigned short) (0x08)
#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11)
#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11)
#define SET_TX_START_THRESH (unsigned short) (0x13<<11)
#define STATS_ENABLE (unsigned short) (0x15<<11)
#define STATS_DISABLE (unsigned short) (0x16<<11)
#define STOP_TRANSCEIVER (unsigned short) (0x17<<11)
/*
* 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 (unsigned short) (0x1)
#define S_CARD_FAILURE (unsigned short) (0x2)
#define S_TX_COMPLETE (unsigned short) (0x4)
#define S_TX_AVAIL (unsigned short) (0x8)
#define S_RX_COMPLETE (unsigned short) (0x10)
#define S_RX_EARLY (unsigned short) (0x20)
#define S_INT_RQD (unsigned short) (0x40)
#define S_UPD_STATS (unsigned short) (0x80)
#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000)
#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS)
/* Address Config. Register.
* Window 0/Port 06
*/
#define ACF_CONNECTOR_BITS 14
#define ACF_CONNECTOR_UTP 0
#define ACF_CONNECTOR_AUI 1
#define ACF_CONNECTOR_BNC 3
#define INTERNAL_CONNECTOR_BITS 20
#define INTERNAL_CONNECTOR_MASK 0x01700000
/*
* FIFO Registers. RX Status.
*
* 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_INCOMPLETE (unsigned short) (0x8000)
#define ERR_RX (unsigned short) (0x4000)
#define ERR_MASK (unsigned short) (0x7800)
#define ERR_OVERRUN (unsigned short) (0x4000)
#define ERR_RUNT (unsigned short) (0x5800)
#define ERR_ALIGNMENT (unsigned short) (0x6000)
#define ERR_CRC (unsigned short) (0x6800)
#define ERR_OVERSIZE (unsigned short) (0x4800)
#define ERR_DRIBBLE (unsigned short) (0x1000)
/*
* TX Status.
*
* 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_INTR_REQ 0x40
#define TXS_JABBER 0x20
#define TXS_UNDERRUN 0x10
#define TXS_MAX_COLLISION 0x8
#define TXS_STATUS_OVERFLOW 0x4
#define RS_AUI (1<<5)
#define RS_BNC (1<<4)
#define RS_UTP (1<<3)
#define RS_T4 (1<<0)
#define RS_TX (1<<1)
#define RS_FX (1<<2)
#define RS_MII (1<<6)
/*
* FIFO Status (Window 4)
*
* Supports FIFO diagnostics
*
* Window 4/Port 0x04.1
*
* 15: 1=RX receiving (RO). Set when a packet is being received
* into the RX FIFO.
* 14: Reserved
* 13: 1=RX underrun (RO). Generates Adapter Failure interrupt.
* Requires RX Reset or Global Reset command to recover.
* It is generated when you read past the end of a packet -
* reading past what has been received so far will give bad
* data.
* 12: 1=RX status overrun (RO). Set when there are already 8
* packets in the RX FIFO. While this bit is set, no additional
* packets are received. Requires no action on the part of
* the host. The condition is cleared once a packet has been
* read out of the RX FIFO.
* 11: 1=RX overrun (RO). Set when the RX FIFO is full (there
* may not be an overrun packet yet). While this bit is set,
* no additional packets will be received (some additional
* bytes can still be pending between the wire and the RX
* FIFO). Requires no action on the part of the host. The
* condition is cleared once a few bytes have been read out
* from the RX FIFO.
* 10: 1=TX overrun (RO). Generates adapter failure interrupt.
* Requires TX Reset or Global Reset command to recover.
* Disables Transmitter.
* 9-8: Unassigned.
* 7-0: Built in self test bits for the RX and TX FIFO's.
*/
#define FIFOS_RX_RECEIVING (unsigned short) 0x8000
#define FIFOS_RX_UNDERRUN (unsigned short) 0x2000
#define FIFOS_RX_STATUS_OVERRUN (unsigned short) 0x1000
#define FIFOS_RX_OVERRUN (unsigned short) 0x0800
#define FIFOS_TX_OVERRUN (unsigned short) 0x0400
/*
* Misc defines for various things.
*/
#define TAG_ADAPTER 0xd0
#define ACTIVATE_ADAPTER_TO_CONFIG 0xff
#define ENABLE_DRQ_IRQ 0x0001
#define MFG_ID 0x506d /* `TCM' */
#define PROD_ID 0x5090
#define GO_WINDOW(x) outw(WINDOW_SELECT|(x),BASE+VX_COMMAND)
#define JABBER_GUARD_ENABLE 0x40
#define LINKBEAT_ENABLE 0x80
#define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE)
#define DISABLE_UTP 0x0
#define RX_BYTES_MASK (unsigned short) (0x07ff)
#define RX_ERROR 0x4000
#define RX_INCOMPLETE 0x8000
#define TX_INDICATE 1<<15
#define is_eeprom_busy(b) (inw((b)+VX_W0_EEPROM_COMMAND)&EEPROM_BUSY)
#define VX_IOSIZE 0x20
#define VX_CONNECTORS 8
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View file

@ -1,4 +1,4 @@
/*
/*
* 3c90x.c -- This file implements the 3c90x driver for etherboot. Written
* by Greg Beeley, Greg.Beeley@LightSys.org. Modified by Steve Smith,
* Steve.Smith@Juno.Com
@ -6,13 +6,13 @@
* This program Copyright (C) 1999 LightSys Technology Services, Inc.
* Portions Copyright (C) 1999 Steve Smith
*
* This program may be re-distributed in source or binary form, modified,
* This program may be re-distributed in source or binary form, modified,
* sold, or copied for any purpose, provided that the above copyright message
* and this text are included with all source copies or derivative works, and
* provided that the above copyright message and this text are included in the
* documentation of any binary-only distributions. This program is distributed
* WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR A PARTICULAR
* PURPOSE or MERCHANTABILITY. Please read the associated documentation
* PURPOSE or MERCHANTABILITY. Please read the associated documentation
* "3c90x.txt" before compiling and using this driver.
*
* --------
@ -37,11 +37,7 @@
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#if 0
#ifndef __FreeBSD__
#include <linux/pci.h>
#endif
#endif
#include "cards.h"
#define TIME_OUT 60000
#define XCVR_MAGIC (0x5A00)
@ -261,7 +257,7 @@ a3c90x_internal_IssueCommand(int ioaddr, int cmd, int param)
{
unsigned int val;
/** Build the cmd. **/
/** Build the cmd. **/
val = cmd;
val <<= 11;
val |= param;
@ -282,7 +278,7 @@ static int
a3c90x_internal_SetWindow(int ioaddr, int window)
{
/** Window already as set? **/
/** Window already as set? **/
if (INF_3C90X.CurrentWindow == window) return 0;
/** Issue the window command. **/
@ -303,7 +299,7 @@ a3c90x_internal_ReadEeprom(int ioaddr, int address)
/** Select correct window **/
a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winEepromBios0);
/** Make sure the eeprom isn't busy **/
/** Make sure the eeprom isn't busy **/
while((1<<15) & inw(ioaddr + regEepromCommand_0_w));
/** Read the value. **/
@ -315,7 +311,7 @@ a3c90x_internal_ReadEeprom(int ioaddr, int address)
}
/*** a3c90x_internal_WriteEepromWord - write a physical word of
/*** a3c90x_internal_WriteEepromWord - write a physical word of
*** data to the onboard serial eeprom (not the BIOS prom, but the
*** nvram in the card that stores, among other things, the MAC
*** address).
@ -323,7 +319,7 @@ a3c90x_internal_ReadEeprom(int ioaddr, int address)
static int
a3c90x_internal_WriteEepromWord(int ioaddr, int address, unsigned short value)
{
/** Select register window **/
/** Select register window **/
a3c90x_internal_SetWindow(ioaddr, winEepromBios0);
/** Verify Eeprom not busy **/
@ -371,7 +367,7 @@ a3c90x_internal_WriteEeprom(int ioaddr, int address, unsigned short value)
cksumAddress=0x17;
}
/** Write the value. **/
/** Write the value. **/
if (a3c90x_internal_WriteEepromWord(ioaddr, address, value) == -1)
return -1;
@ -397,12 +393,12 @@ a3c90x_internal_WriteEeprom(int ioaddr, int address, unsigned short value)
*** not alter the selected transceiver that we used to download the boot
*** image.
***/
static void
static void
a3c90x_reset(struct nic *nic)
{
int cfg;
#ifdef CFG_3C90X_PRESERVE_XCVR
#ifdef CFG_3C90X_PRESERVE_XCVR
/** Read the current InternalConfig value. **/
a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3);
cfg = inl(INF_3C90X.IOAddr + regInternalConfig_3_l);
@ -415,7 +411,7 @@ a3c90x_reset(struct nic *nic)
/** wait for reset command to complete **/
while (inw(INF_3C90X.IOAddr + regCommandIntStatus_w) & INT_CMDINPROGRESS);
/** global reset command resets station mask, non-B revision cards
/** global reset command resets station mask, non-B revision cards
** require explicit reset of values
**/
a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winAddressing2);
@ -423,7 +419,7 @@ a3c90x_reset(struct nic *nic)
outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+2);
outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+4);
#ifdef CFG_3C90X_PRESERVE_XCVR
#ifdef CFG_3C90X_PRESERVE_XCVR
/** Re-set the original InternalConfig value from before reset **/
a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winTxRxOptions3);
outl(cfg, INF_3C90X.IOAddr + regInternalConfig_3_l);
@ -476,12 +472,12 @@ a3c90x_reset(struct nic *nic)
*** s - size of the non-header part of the packet that needs transmitted;
*** p - the pointer to the packet data itself.
***/
static void
a3c90x_transmit(struct nic *nic, char *d, unsigned int t,
unsigned int s, char *p)
static void
a3c90x_transmit(struct nic *nic, const char *d, unsigned int t,
unsigned int s, const char *p)
{
struct eth_hdr
struct eth_hdr
{
unsigned char dst_addr[6];
unsigned char src_addr[6];
@ -539,7 +535,7 @@ a3c90x_transmit(struct nic *nic, char *d, unsigned int t,
if (timeout==0)
{
printf("3C90X: Transmission Timeout\n");
printf("3C90X: Tx Timeout\n");
continue;
}
@ -556,31 +552,31 @@ a3c90x_transmit(struct nic *nic, char *d, unsigned int t,
/** check error codes **/
if (status & 0x02)
{
printf("3C90X: Transmitter Reclaim Error (%x)\n", status);
printf("3C90X: Tx Reclaim Error (%x)\n", status);
a3c90x_reset(NULL);
}
else if (status & 0x04)
{
printf("3C90X: Transmitter Status Overflow (%x)\n", status);
for (i=0; i<32; i++)
printf("3C90X: Tx Status Overflow (%x)\n", status);
for (i=0; i<32; i++)
outb(0x00, INF_3C90X.IOAddr + regTxStatus_b);
/** must re-enable after max collisions before re-issuing tx **/
a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxEnable, 0);
}
else if (status & 0x08)
{
printf("3C90X: Transmitter Max Collisions (%x)\n", status);
printf("3C90X: Tx Max Collisions (%x)\n", status);
/** must re-enable after max collisions before re-issuing tx **/
a3c90x_internal_IssueCommand(INF_3C90X.IOAddr, cmdTxEnable, 0);
}
else if (status & 0x10)
{
printf("3C90X: Transmitter Underrun (%x)\n", status);
printf("3C90X: Tx Underrun (%x)\n", status);
a3c90x_reset(NULL);
}
else if (status & 0x20)
{
printf("3C90X: Transmitter Jabber (%x)\n", status);
printf("3C90X: Tx Jabber (%x)\n", status);
a3c90x_reset(NULL);
}
else if ((status & 0x80) != 0x80)
@ -604,7 +600,7 @@ a3c90x_transmit(struct nic *nic, char *d, unsigned int t,
*** copy the packet to nic->packet if it gets a packet and set the size
*** in nic->packetlen. Return 1 if a packet was found.
***/
static int
static int
a3c90x_poll(struct nic *nic)
{
int i, errcode;
@ -634,11 +630,11 @@ a3c90x_poll(struct nic *nic)
for(i=0;i<40000;i++);
/** Check for Error (else we have good packet) **/
if (INF_3C90X.ReceiveUPD.UpPktStatus & (1<<14))
if (INF_3C90X.ReceiveUPD.UpPktStatus & (1<<14))
{
errcode = INF_3C90X.ReceiveUPD.UpPktStatus;
if (errcode & (1<<16))
printf("3C90X: Receiver Overrun (%x)\n",errcode>>16);
printf("3C90X: Rx Overrun (%x)\n",errcode>>16);
else if (errcode & (1<<17))
printf("3C90X: Runt Frame (%x)\n",errcode>>16);
else if (errcode & (1<<18))
@ -657,14 +653,14 @@ a3c90x_poll(struct nic *nic)
return 1;
}
/*** a3c90x_disable: exported routine to disable the card. What's this for?
*** the eepro100.c driver didn't have one, so I just left this one empty too.
*** Ideas anyone?
***/
static void
static void
a3c90x_disable(struct nic *nic)
{
}
@ -676,9 +672,9 @@ a3c90x_disable(struct nic *nic)
*** card. We just have to init it here.
***/
struct nic*
a3c90x_probe(struct nic *nic, unsigned short *probeaddrs)
a3c90x_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_device *pci)
{
int i, j, to, v, c;
int i, c;
unsigned short eeprom[0x21];
unsigned int cfg;
unsigned int mopt;
@ -695,7 +691,7 @@ a3c90x_probe(struct nic *nic, unsigned short *probeaddrs)
case 0x9001: /** 10/100 T4 **/
case 0x9050: /** 10/100 TPO **/
case 0x9051: /** 10 Base Combo **/
INF_3C90X.isBrev = 0;
INF_3C90X.isBrev = 0;
break;
case 0x9004: /** 10 Base TPO **/
@ -706,7 +702,7 @@ a3c90x_probe(struct nic *nic, unsigned short *probeaddrs)
case 0x9056: /** 10/100 T4 **/
case 0x905A: /** 10 Base FX **/
default:
INF_3C90X.isBrev = 1;
INF_3C90X.isBrev = 1;
break;
}
@ -718,11 +714,13 @@ a3c90x_probe(struct nic *nic, unsigned short *probeaddrs)
eeprom[i] = a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, i);
}
#ifdef CFG_3C90X_BOOTROM_FIX
/** Set xcvrSelect in InternalConfig in eeprom. **/
/* only necessary for 3c905b revision cards with boot PROM bug!!! */
a3c90x_internal_WriteEeprom(INF_3C90X.IOAddr, 0x13, 0x0160);
a3c90x_internal_WriteEeprom(INF_3C90X.IOAddr, 0x13, 0x0160);
#endif
#ifdef CFG_3C90X_XCVR
#ifdef CFG_3C90X_XCVR
if (CFG_3C90X_XCVR == 255)
{
/** Clear the LanWorks register **/
@ -795,27 +793,27 @@ a3c90x_probe(struct nic *nic, unsigned short *probeaddrs)
printf("Connectors present: ");
c = 0;
linktype = 0x0008;
if (mopt & 0x01)
if (mopt & 0x01)
{
printf("%s100Base-T4",(c++)?", ":"");
linktype = 0x0006;
}
if (mopt & 0x04)
if (mopt & 0x04)
{
printf("%s100Base-FX",(c++)?", ":"");
linktype = 0x0005;
}
if (mopt & 0x10)
if (mopt & 0x10)
{
printf("%s10Base-2",(c++)?", ":"");
linktype = 0x0003;
}
if (mopt & 0x20)
if (mopt & 0x20)
{
printf("%sAUI",(c++)?", ":"");
linktype = 0x0001;
}
if (mopt & 0x40)
if (mopt & 0x40)
{
printf("%sMII",(c++)?", ":"");
linktype = 0x0006;
@ -850,10 +848,10 @@ a3c90x_probe(struct nic *nic, unsigned short *probeaddrs)
}
else
{
#ifdef CFG_3C90X_XCVR
#ifdef CFG_3C90X_XCVR
if (CFG_3C90X_XCVR != 255)
linktype = CFG_3C90X_XCVR;
#endif // CFG_3C90X_XCVR
#endif /* CFG_3C90X_XCVR */
/** I don't know what MII MAC only mode is!!! **/
if (linktype == 0x0009)

View file

@ -1,14 +1,18 @@
Instructions for use of the 3C90X driver for EtherBoot
Instructions for use of the 3C90X driver for EtherBoot
Original 3C905B support by:
Greg Beeley (Greg.Beeley@LightSys.org),
LightSys Technology Services, Inc.
February 11, 1999
Original 3C905B support by:
Greg Beeley (Greg.Beeley@LightSys.org),
LightSys Technology Services, Inc.
February 11, 1999
Updates for 3C90X family by:
Steve Smith (steve.smith@juno.com)
October 1, 1999
Updates for 3C90X family by:
Steve Smith (steve.smith@juno.com)
October 1, 1999
Minor documentation updates by
Greg Beeley (Greg.Beeley@LightSys.org)
March 29, 2000
-------------------------------------------------------------------------------
@ -16,38 +20,39 @@ I OVERVIEW
The 3c90X series ethernet cards are a group of high-performance busmaster
DMA cards from 3Com. This particular driver supports both the 3c90x and
the 3c90xB revision cards. 3C90xC family support is not yet available.
the 3c90xB revision cards. 3C90xC family support has been tested to some
degree but not extensively.
Here's the licensing information:
This program Copyright (C) 1999 LightSys Technology Services, Inc.
Portions Copyright (C) 1999 Steve Smith.
This program may be re-distributed in source or binary form, modified,
sold, or copied for any purpose, provided that the above copyright message
and this text are included with all source copies or derivative works, and
provided that the above copyright message and this text are included in the
documentation of any binary-only distributions. This program is distributed
WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR A PARTICULAR
PURPOSE or MERCHANTABILITY. Please read the associated documentation
"3c90x.txt" before compiling and using this driver.
documentation of any binary-only distributions. This program is
distributed WITHOUT ANY WARRANTY, without even the warranty of FITNESS FOR
A PARTICULAR PURPOSE or MERCHANTABILITY. Please read the associated
documentation "3c90x.txt" before compiling and using this driver.
II FLASH PROMS
The 3c90xB cards, according to the 3Com documentation, only accept the
The 3c90xB cards, according to the 3Com documentation, only accept the
following flash memory chips:
Atmel AT29C512 (64 kilobyte)
Atmel AT29C010 (128 kilobyte)
Atmel AT29C512 (64 kilobyte)
Atmel AT29C010 (128 kilobyte)
The 3c90x cards, according to the 3Com documentation, accept the
The 3c90x cards, according to the 3Com documentation, accept the
following flash memory chips capacities:
64 kb (8 kB)
128 kb (16 kB)
256 kb (32 kB) and
512 kb (64 kB)
64 kb (8 kB)
128 kb (16 kB)
256 kb (32 kB) and
512 kb (64 kB)
Atmel AT29C512 (64 kilobyte) chips are specifically listed for both
adapters, but flashing on the 3c905b cards would only be supported
@ -55,87 +60,87 @@ II FLASH PROMS
be supported when programmed by a dedicated PROM programmer (e.g.
not the card).
To use this driver in such a PROM, visit Atmel's web site and download their
.PDF file containing a list of their distributors. Contact the distributors
for pricing information. The prices are quite reasonable (about $3 US each
for the 64 kB part), and are comparable to what one would expect for
similarly sized standard EPROMs. And, the flash chips are much easier to
work with, as they don't need to be UV-erased to be reprogrammed. The
3C905B card actually provides a method to program the flash memory while
it is resident on board the card itself; if someone would like to write a
small DOS program to do the programming, I can provide the information
about the registers and so forth.
To use this driver in such a PROM, visit Atmel's web site and download
their .PDF file containing a list of their distributors. Contact the
distributors for pricing information. The prices are quite reasonable
(about $3 US each for the 64 kB part), and are comparable to what one would
expect for similarly sized standard EPROMs. And, the flash chips are much
easier to work with, as they don't need to be UV-erased to be reprogrammed.
The 3C905B card actually provides a method to program the flash memory
while it is resident on board the card itself; if someone would like to
write a small DOS program to do the programming, I can provide the
information about the registers and so forth.
Better yet, for those using Linux it might be even better if the programming
could be done while Linux is running, either via a modification to the 3c59x
driver or via some other program/driver. That way, a system administrator
on a private network could update all the NC flash images from a centrally
managed location.
A utility program, 3c90xutil, is provided with Etherboot in the 'contrib'
directory that allows for the on-board flashing of the ROM while Linux
is running. The program has been successfully used under Linux, but I
have heard problem reports of its use under FreeBSD. Anyone willing to
make it work under FreeBSD is more than welcome to do so!
III GENERAL USE
Normally, the basic procedure for using this driver is as follows:
1. Run the 3c90xcfg program on the driver diskette to enable the
boot PROM and set it to 64k or 128k, as appropriate.
2. Edit Config (in the src-32 directory) and define the
90X_SIGNATURE for your particular adapter (model numbers and
corresponding values are listed in the file)
3. Build the 3c90x.fd0 floppy image with possibly the value
CFG_3C90X_XCVR defined to the transceiver type that you want
to use (i.e., 10/100 rj45, AUI, coax, MII, etc.)
4. Run the floppy image on the PC to be network booted, to get
it configured, and to verify that it will boot properly.
5. Build the 3c90x.rom or 3c90x.lzrom PROM image and program
it into the flash memory chip.
6. Put the PROM in the ethernet card, boot and enable 'boot from
network first' in the system BIOS, save and reboot.
1. Run the 3c90xcfg program on the driver diskette to enable the
boot PROM and set it to 64k or 128k, as appropriate.
2. Build the appropriate 3c90x.fd0 or 3c90x.fd0 floppy image with
possibly the value CFG_3C90X_XCVR defined to the transceiver type that
you want to use (i.e., 10/100 rj45, AUI, coax, MII).
3. Run the floppy image on the PC to be network booted, to verify that
it will boot properly.
4. Build the 3c90x.rom or 3c90x.lzrom PROM image and program
it into the flash memory chip.
5. Put the PROM in the ethernet card, boot and enable 'boot from
network first' in the system BIOS, save and reboot.
Here are some issues to be aware of:
1. A picky BIOS that may work better with NO_PNP_PCI_HEADER
defined to boot the prom image.
2. The possible need to manually set the CFG_3C90X_XCVR value to
configure the transceiver type. Values are listed below.
3. The possible need to define CFG_3C90X_PRESERVE_XCVR for use in
operating systems that don't intelligently determine the
transceiver type.
1. If you experience crashes or different behaviour when using the
boot PROM, add the setting CFG_3C90X_BOOTROM_FIX and go through the
steps 2-5 above. This works around a bug in some 3c905B cards (see
below), but has some side-effects which may not be desirable.
2. The possible need to manually set the CFG_3C90X_XCVR value to
configure the transceiver type. Values are listed below.
3. The possible need to define CFG_3C90X_PRESERVE_XCVR for use in
operating systems that don't intelligently determine the
transceiver type.
Some things that are on the 'To-Do' list, perhaps for me, but perhaps
for any other volunteers out there:
1. Write a DOS- or Linux- based flash programmer for the 3c905b
card, so PROM users don't have to buy a $200 programmer....
2. Extend the driver to fully implement the auto-select
algorithm if the card has multiple media ports.
3. Fix any bugs in the code <grin>....
4. Extend the driver to support the 3c905c revision cards
1. Extend the driver to fully implement the auto-select
algorithm if the card has multiple media ports.
2. Fix any bugs in the code <grin>....
3. Extend the driver to support the 3c905c revision cards
"officially". Right now, the support has been primarily empirical
and not based on 3c905C documentation.
Now for the details....
This driver has been tested on roughly 300 systems. The main two
configuration issues to contend with are:
1. Ensure that PCI Busmastering is enabled for the adapter
(configured in the CMOS setup)
2. Some systems don't work properly with the adapter when
plug and play OS is enabled; I always set it to "No" or
"Disabled" -- this makes it easier and really doesn't
adversely affect anything.
1. Ensure that PCI Busmastering is enabled for the adapter (configured
in the CMOS setup)
2. Some systems don't work properly with the adapter when plug and
play OS is enabled; I always set it to "No" or "Disabled" -- this makes
it easier and really doesn't adversely affect anything.
Roughly 95% of the systems worked when configured properly. A few
have issues with booting locally once the boot PROM has been installed
(this number has been less than 2%). Other configuration issues that
to check:
1. Newer BIOS's actually work correctly with the network boot
order. Set the network adapter first. Most older BIOS's
automatically go to the network boot PROM first.
2. For systems where the adapter was already installed and is
just having the PROM installed, try setting the "reset
configuration data" to yes in the CMOS setup if the BIOS isn't
seen at first. If your BIOS doesn't have this option, remove
the card, start the system, shut down, install the card and
restart (or switch to a different PCI slot).
3. Make sure the CMOS security settings aren't preventing a boot.
1. Newer BIOS's actually work correctly with the network boot order.
Set the network adapter first. Most older BIOS's automatically go to
the network boot PROM first.
2. For systems where the adapter was already installed and is just
having the PROM installed, try setting the "reset configuration data"
to yes in the CMOS setup if the BIOS isn't seen at first. If your BIOS
doesn't have this option, remove the card, start the system, shut down,
install the card and restart (or switch to a different PCI slot).
3. Make sure the CMOS security settings aren't preventing a boot.
The 3c905B cards have a significant 'bug' that relates to the flash prom:
unless the card is set internally to the MII transceiver, it will only
@ -143,7 +148,9 @@ III GENERAL USE
obscure, but it has to do with the way they mux'd the address lines
from the PCI bus to the ROM. Unfortunately, most of us are not using
MII transceivers, and even the .lzrom image ends up being just a little
bit larger than 8k.
bit larger than 8k. Note that the workaround for this is disabled by
default, because the Windows NT 4.0 driver does not like it (no packets
are transmitted).
So, the solution that I've used is to internally set the card's nvram
configuration to use MII when it boots. The 3c905b driver does this
@ -152,29 +159,32 @@ III GENERAL USE
card to an appropriate value, either configurable by the user or chosen
by the driver.
To enable the 3c905B bugfix, which is necessary for these cards when
booting from the Flash ROM, define -DCFG_3C90X_BOOTROM_FIX when building.
The driver should choose an appropriate transceiver on the card. However,
if it doesn't on your card or if you need to, for instance, set your
if it doesn't on your card or if you need to, for instance, set your
card to 10mbps when connected to an unmanaged 10/100 hub, you can specify
which transceiver you want to use. To do this, build the 3c905b.fd0
image with -DCFG_3C905B_XCVR=x, where 'x' is one of the following
image with -DCFG_3C90X_XCVR=x, where 'x' is one of the following
values:
0 10Base-T
1 10mbps AUI
3 10Base-2 (thinnet/coax)
4 100Base-TX
5 100Base-FX
6 MII
8 Auto-negotiation 10Base-T / 100Base-TX (usually the default)
9 MII External MAC Mode
255 Allow driver to choose an 'appropriate' media port.
0 10Base-T
1 10mbps AUI
3 10Base-2 (thinnet/coax)
4 100Base-TX
5 100Base-FX
6 MII
8 Auto-negotiation 10Base-T / 100Base-TX (usually the default)
9 MII External MAC Mode
255 Allow driver to choose an 'appropriate' media port.
Then proceed from step 2 in the above 'general use' instructions. The
.rom image can be built with CFG_3C90X_XCVR set to a value, but you
normally don't want to do this, since it is easier to change the
normally don't want to do this, since it is easier to change the
transceiver type by rebuilding a new floppy, changing the BIOS to floppy
boot, booting, and then changing the BIOS back to network boot. If
CFG_3C90X_XCVR is not set in a particular build, it just uses the
CFG_3C90X_XCVR is not set in a particular build, it just uses the
current configuration (either its 'best guess' or whatever the stored
CFG_3C90X_XCVR value was from the last time it was set).
@ -182,7 +192,7 @@ III GENERAL USE
programmed into a register in the card's NVRAM that was reserved for
LanWorks PROM images to use. When the driver boots, the card comes
up in MII mode, and the driver checks the LanWorks register to find
out if the user specified a transceiver type. If it finds that
out if the user specified a transceiver type. If it finds that
information, it uses that, otherwise it picks a transceiver that the
card has based on the 3c905b's MediaOptions register. This driver isn't
quite smart enough to always determine which media port is actually
@ -193,7 +203,7 @@ III GENERAL USE
Another issue to keep in mind is that it is possible that some OS'es
might not be happy with the way I've handled the PROM-image hack with
setting MII mode on bootup. Linux 2.0.35 does not have this problem.
I haven't tested anything else. The 3com documentation specifically
Behavior of other systems may vary. The 3com documentation specifically
says that, at least with the card that I have, the device driver in the
OS should auto-select the media port, so other drivers should work fine
with this 'hack'. However, if yours doesn't seem to, you can try defining
@ -211,58 +221,58 @@ IV FOR DEVELOPERS....
A. Main Entry Point
a3c90x_probe is the main entry point for this driver. It is referred
to in an array in 'config.c'.
a3c90x_probe is the main entry point for this driver. It is referred
to in an array in 'config.c'.
B. Other Exported Functions
B. Other Important Functions
The functions a3c90x_transmit, a3c90x_poll, a3c90x_reset, and
a3c90x_disable are exported functions that EtherBoot finds out about
as a result of a3c90x_probe setting entries in the nic structure
for them. The EtherBoot framework does not use interrupts. It is
polled. All transmit and receive operations are initiated by the
etherboot framework, not by an interrupt or by the driver.
The functions a3c90x_transmit, a3c90x_poll, a3c90x_reset, and
a3c90x_disable are static functions that EtherBoot finds out about
as a result of a3c90x_probe setting entries in the nic structure
for them. The EtherBoot framework does not use interrupts. It is
polled. All transmit and receive operations are initiated by the
etherboot framework, not by an interrupt or by the driver.
C. Internal Functions
The following functions are internal to the driver:
The following functions are internal to the driver:
a3c90x_internal_IssueCommand - sends a command to the 3c905b card.
a3c90x_internal_SetWindow - shifts between one of eight register
windows onboard the 3c90x. The bottom 16 bytes of the card's
I/O space are multiplexed among 128 bytes, only 16 of which are
visible at any one time. This SetWindow function selects one of
the eight sets.
a3c90x_internal_ReadEeprom - reads a word (16 bits) from the
card's onboard nvram. This is NOT the BIOS boot rom. This is
where the card stores such things as its hardware address.
a3c90x_internal_WriteEeprom - writes a word (16 bits) to the
card's nvram, and recomputes the eeprom checksum.
a3c90x_internal_WriteEepromWord - writes a word (16 bits) to the
card's nvram. Used by the above routine.
a3c90x_internal_WriteEepromWord - writes a word (16 bits) to the
card's nvram. Used by the above routine.
a3c90x_internal_IssueCommand - sends a command to the 3c905b card.
a3c90x_internal_SetWindow - shifts between one of eight register
windows onboard the 3c90x. The bottom 16 bytes of the card's
I/O space are multiplexed among 128 bytes, only 16 of which are
visible at any one time. This SetWindow function selects one of
the eight sets.
a3c90x_internal_ReadEeprom - reads a word (16 bits) from the
card's onboard nvram. This is NOT the BIOS boot rom. This is
where the card stores such things as its hardware address.
a3c90x_internal_WriteEeprom - writes a word (16 bits) to the
card's nvram, and recomputes the eeprom checksum.
a3c90x_internal_WriteEepromWord - writes a word (16 bits) to the
card's nvram. Used by the above routine.
a3c90x_internal_WriteEepromWord - writes a word (16 bits) to the
card's nvram. Used by the above routine.
D. Globals
All global variables are inside a global structure named INF_3C90X.
So, wherever you see that structure referenced, you know the variable
is a global. Just keeps things a little neater.
All global variables are inside a global structure named INF_3C90X.
So, wherever you see that structure referenced, you know the variable
is a global. Just keeps things a little neater.
E. Enumerations
There are quite a few enumerated type definitions for registers and
so forth, many for registers that I didn't even touch in the driver.
Register types start with 'reg', window numbers (for SetWindow)
start with 'win', and commands (for IssueCommand) start with 'cmd'.
Register offsets also include an indication in the name as to the
size of the register (_b = byte, _w = word, _l = long), and which
window the register is in, if it is windowed (0-7).
There are quite a few enumerated type definitions for registers and
so forth, many for registers that I didn't even touch in the driver.
Register types start with 'reg', window numbers (for SetWindow)
start with 'win', and commands (for IssueCommand) start with 'cmd'.
Register offsets also include an indication in the name as to the
size of the register (_b = byte, _w = word, _l = long), and which
window the register is in, if it is windowed (0-7).
F. Why the 'a3c90x' name?
I had to come up with a letter at the beginning of all of the
identifiers, since 3com so conveniently had their name start with a
number. Another driver used 't' (for 'three'?); I chose 'a' for
no reason at all.
I had to come up with a letter at the beginning of all of the
identifiers, since 3com so conveniently had their name start with a
number. Another driver used 't' (for 'three'?); I chose 'a' for
no reason at all.

View file

@ -10,36 +10,37 @@ endif
noinst_LIBRARIES = $(LIBDRIVERS)
libdrivers_a_SOURCES = byteorder.h config.c etherboot.h \
fsys_tftp.c if.h linux-asm-io.h linux-asm-string.h \
main.c misc.c netboot_config.h netdevice.h nic.h osdep.h \
pci.c pci.h
EXTRA_libdrivers_a_SOURCES = 3c509.c 3c509.h 3c90x.c cs89x0.c \
cs89x0.h eepro100.c epic100.c epic100.h i82586.c lance.c \
ns8390.c ns8390.h ntulip.c rtl8139.c sk_g16.c sk_g16.h \
smc9000.c smc9000.h tiara.c tulip.c tulip.h via-rhine.c
libdrivers_a_SOURCES = cards.h config.c etherboot.h \
fsys_tftp.c linux-asm-io.h linux-asm-string.h \
main.c misc.c nic.h osdep.h pci.c pci.h
EXTRA_libdrivers_a_SOURCES = 3c509.c 3c509.h 3c595.c 3c595.h 3c90x.c \
cs89x0.c cs89x0.h depca.c eepro100.c epic100.c epic100.h \
i82586.c lance.c ns8390.c ns8390.h otulip.c otulip.h rtl8139.c \
sk_g16.c sk_g16.h smc9000.c smc9000.h tiara.c tulip.c \
via-rhine.c
libdrivers_a_CFLAGS = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-DFSYS_TFTP $(NET_CFLAGS) $(NET_EXTRAFLAGS)
-DFSYS_TFTP=1 $(NET_CFLAGS) $(NET_EXTRAFLAGS)
# Filled by configure.
libdrivers_a_LIBADD = @NETBOOT_DRIVERS@
libdrivers_a_DEPENDENCIES = $(libdrivers_a_LIBADD)
EXTRA_DIST = README.netboot 3c90x.txt ntulip.txt
EXTRA_DIST = README.netboot 3c90x.txt cs89x0.txt tulip.txt
# These below are several special rules for the device drivers.
# We cannot use a simple rule for them...
# What objects are derived from a driver?
3c509_drivers = 3c509.o 3c529.o
#3c59x_drivers = 3c59x.o
3c595_drivers = 3c590.o 3c595.o
3c90x_drivers = 3c90x.o
cs89x0_drivers = cs89x0.o
depca_drivers = depca.o
eepro100_drivers = eepro100.o
epic100_drivers = epic100.o
i82586_drivers = 3c507.o exos205.o ni5210.o
lance_drivers = lancepci.o ne2100.o ni6510.o
ns8390_drivers = 3c503.o ne.o nepci.o wd.o
ntulip_drivers = ntulip.o
lance_drivers = lance.o ne2100.o ni6510.o
ns8390_drivers = 3c503.o ne.o ns8390.o wd.o
otulip_drivers = otulip.o
rtl8139_drivers = rtl8139.o
sk_g16_drivers = sk_g16.o
smc9000_drivers = smc9000.o
@ -63,10 +64,10 @@ $(3c509_drivers): %.o: 3c509.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
#$(3c59x_drivers): 3c59x.c 3c509.h
#$(3c59x_drivers): %.o: 3c59x.c
# $(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
# $(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(3c595_drivers): 3c595.c 3c595.h
$(3c595_drivers): %.o: 3c595.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(3c90x_drivers): 3c90x.c
$(3c90x_drivers): %.o: 3c90x.c
@ -78,6 +79,11 @@ $(cs89x0_drivers): %.o: cs89x0.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(depca_drivers): depca.c
$(depca_drivers): %.o: depca.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(eepro100_drivers): eepro100.c
$(eepro100_drivers): %.o: eepro100.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
@ -93,8 +99,8 @@ $(lance_drivers): %.o: lance.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(ntulip_drivers): ntulip.c
$(ntulip_drivers): %.o: ntulip.c
$(tulip_drivers): tulip.c
$(tulip_drivers): %.o: tulip.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
@ -118,8 +124,8 @@ $(tiara_drivers): %.o: tiara.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(tulip_drivers): tulip.c tulip.h
$(tulip_drivers): %.o: tulip.c
$(otulip_drivers): otulip.c otulip.h
$(otulip_drivers): %.o: otulip.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
@ -132,22 +138,24 @@ $(via_rhine_drivers): %.o: via-rhine.c
# Per-object flags.
3c509_o_CFLAGS = -DINCLUDE_3C509=1
3c529_o_CFLAGS = -DINCLUDE_3C529=1
#3c59x_o_CFLAGS = -DINCLUDE_3C59X=1
3c590_o_CFLAGS = -DINCLUDE_3C590=1
3c595_o_CFLAGS = -DINCLUDE_3C595=1
3c90x_o_CFLAGS = -DINCLUDE_3C90X=1
cs89x0_o_CFLAGS = -DINCLUDE_CS89X0=1
depca_o_CFLAGS = -DINCLUDE_DEPCA=1
eepro100_o_CFLAGS = -DINCLUDE_EEPRO100=1
epic100_o_CFLAGS = -DINCLUDE_EPIC100=1
3c507_o_CFLAGS = -DINCLUDE_3C507=1
exos205_o_CFLAGS = -DINCLUDE_EXOS205=1
ni5210_o_CFLAGS = -DINCLUDE_NI5210=1
lancepci_o_CFLAGS = -DINCLUDE_LANCEPCI=1
lance_o_CFLAGS = -DINCLUDE_LANCE=1
ne2100_o_CFLAGS = -DINCLUDE_NE2100=1
ni6510_o_CFLAGS = -DINCLUDE_NI6510=1
3c503_o_CFLAGS = -DINCLUDE_3C503=1
ne_o_CFLAGS = -DINCLUDE_NE=1
nepci_o_CFLAGS = -DINCLUDE_NEPCI=1
ns8390_o_CFLAGS = -DINCLUDE_NS8390=1
wd_o_CFLAGS = -DINCLUDE_WD=1
ntulip_o_CFLAGS = -DINCLUDE_NTULIP=1
otulip_o_CFLAGS = -DINCLUDE_OTULIP=1
rtl8139_o_CFLAGS = -DINCLUDE_RTL8139=1
sk_g16_o_CFLAGS = -DINCLUDE_SK_G16=1
smc9000_o_CFLAGS = -DINCLUDE_SMC9000=1

View file

@ -95,39 +95,40 @@ INCLUDES = -I$(top_srcdir)/stage2 -I$(top_srcdir)/stage1
noinst_LIBRARIES = $(LIBDRIVERS)
libdrivers_a_SOURCES = byteorder.h config.c etherboot.h \
fsys_tftp.c if.h linux-asm-io.h linux-asm-string.h \
main.c misc.c netboot_config.h netdevice.h nic.h osdep.h \
pci.c pci.h
libdrivers_a_SOURCES = cards.h config.c etherboot.h \
fsys_tftp.c linux-asm-io.h linux-asm-string.h \
main.c misc.c nic.h osdep.h pci.c pci.h
EXTRA_libdrivers_a_SOURCES = 3c509.c 3c509.h 3c90x.c cs89x0.c \
cs89x0.h eepro100.c epic100.c epic100.h i82586.c lance.c \
ns8390.c ns8390.h ntulip.c rtl8139.c sk_g16.c sk_g16.h \
smc9000.c smc9000.h tiara.c tulip.c tulip.h via-rhine.c
EXTRA_libdrivers_a_SOURCES = 3c509.c 3c509.h 3c595.c 3c595.h 3c90x.c \
cs89x0.c cs89x0.h depca.c eepro100.c epic100.c epic100.h \
i82586.c lance.c ns8390.c ns8390.h otulip.c otulip.h rtl8139.c \
sk_g16.c sk_g16.h smc9000.c smc9000.h tiara.c tulip.c \
via-rhine.c
libdrivers_a_CFLAGS = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-DFSYS_TFTP $(NET_CFLAGS) $(NET_EXTRAFLAGS)
-DFSYS_TFTP=1 $(NET_CFLAGS) $(NET_EXTRAFLAGS)
# Filled by configure.
libdrivers_a_LIBADD = @NETBOOT_DRIVERS@
libdrivers_a_DEPENDENCIES = $(libdrivers_a_LIBADD)
EXTRA_DIST = README.netboot 3c90x.txt ntulip.txt
EXTRA_DIST = README.netboot 3c90x.txt cs89x0.txt tulip.txt
# These below are several special rules for the device drivers.
# We cannot use a simple rule for them...
# What objects are derived from a driver?
3c509_drivers = 3c509.o 3c529.o
#3c59x_drivers = 3c59x.o
3c595_drivers = 3c590.o 3c595.o
3c90x_drivers = 3c90x.o
cs89x0_drivers = cs89x0.o
depca_drivers = depca.o
eepro100_drivers = eepro100.o
epic100_drivers = epic100.o
i82586_drivers = 3c507.o exos205.o ni5210.o
lance_drivers = lancepci.o ne2100.o ni6510.o
ns8390_drivers = 3c503.o ne.o nepci.o wd.o
ntulip_drivers = ntulip.o
lance_drivers = lance.o ne2100.o ni6510.o
ns8390_drivers = 3c503.o ne.o ns8390.o wd.o
otulip_drivers = otulip.o
rtl8139_drivers = rtl8139.o
sk_g16_drivers = sk_g16.o
smc9000_drivers = smc9000.o
@ -138,22 +139,24 @@ via_rhine_drivers = via_rhine.o
# Per-object flags.
3c509_o_CFLAGS = -DINCLUDE_3C509=1
3c529_o_CFLAGS = -DINCLUDE_3C529=1
#3c59x_o_CFLAGS = -DINCLUDE_3C59X=1
3c590_o_CFLAGS = -DINCLUDE_3C590=1
3c595_o_CFLAGS = -DINCLUDE_3C595=1
3c90x_o_CFLAGS = -DINCLUDE_3C90X=1
cs89x0_o_CFLAGS = -DINCLUDE_CS89X0=1
depca_o_CFLAGS = -DINCLUDE_DEPCA=1
eepro100_o_CFLAGS = -DINCLUDE_EEPRO100=1
epic100_o_CFLAGS = -DINCLUDE_EPIC100=1
3c507_o_CFLAGS = -DINCLUDE_3C507=1
exos205_o_CFLAGS = -DINCLUDE_EXOS205=1
ni5210_o_CFLAGS = -DINCLUDE_NI5210=1
lancepci_o_CFLAGS = -DINCLUDE_LANCEPCI=1
lance_o_CFLAGS = -DINCLUDE_LANCE=1
ne2100_o_CFLAGS = -DINCLUDE_NE2100=1
ni6510_o_CFLAGS = -DINCLUDE_NI6510=1
3c503_o_CFLAGS = -DINCLUDE_3C503=1
ne_o_CFLAGS = -DINCLUDE_NE=1
nepci_o_CFLAGS = -DINCLUDE_NEPCI=1
ns8390_o_CFLAGS = -DINCLUDE_NS8390=1
wd_o_CFLAGS = -DINCLUDE_WD=1
ntulip_o_CFLAGS = -DINCLUDE_NTULIP=1
otulip_o_CFLAGS = -DINCLUDE_OTULIP=1
rtl8139_o_CFLAGS = -DINCLUDE_RTL8139=1
sk_g16_o_CFLAGS = -DINCLUDE_SK_G16=1
smc9000_o_CFLAGS = -DINCLUDE_SMC9000=1
@ -184,12 +187,13 @@ LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(libdrivers_a_SOURCES) $(EXTRA_libdrivers_a_SOURCES)
depcomp = $(SHELL) $(top_srcdir)/depcomp
DEP_FILES = @AMDEP@ $(DEPDIR)/libdrivers_a-3c509.Po \
$(DEPDIR)/libdrivers_a-3c90x.Po $(DEPDIR)/libdrivers_a-config.Po \
$(DEPDIR)/libdrivers_a-cs89x0.Po $(DEPDIR)/libdrivers_a-eepro100.Po \
$(DEPDIR)/libdrivers_a-3c595.Po $(DEPDIR)/libdrivers_a-3c90x.Po \
$(DEPDIR)/libdrivers_a-config.Po $(DEPDIR)/libdrivers_a-cs89x0.Po \
$(DEPDIR)/libdrivers_a-depca.Po $(DEPDIR)/libdrivers_a-eepro100.Po \
$(DEPDIR)/libdrivers_a-epic100.Po $(DEPDIR)/libdrivers_a-fsys_tftp.Po \
$(DEPDIR)/libdrivers_a-i82586.Po $(DEPDIR)/libdrivers_a-lance.Po \
$(DEPDIR)/libdrivers_a-main.Po $(DEPDIR)/libdrivers_a-misc.Po \
$(DEPDIR)/libdrivers_a-ns8390.Po $(DEPDIR)/libdrivers_a-ntulip.Po \
$(DEPDIR)/libdrivers_a-ns8390.Po $(DEPDIR)/libdrivers_a-otulip.Po \
$(DEPDIR)/libdrivers_a-pci.Po $(DEPDIR)/libdrivers_a-rtl8139.Po \
$(DEPDIR)/libdrivers_a-sk_g16.Po $(DEPDIR)/libdrivers_a-smc9000.Po \
$(DEPDIR)/libdrivers_a-tiara.Po $(DEPDIR)/libdrivers_a-tulip.Po \
@ -238,14 +242,16 @@ libdrivers_a-main.o: main.c
libdrivers_a-misc.o: misc.c
libdrivers_a-pci.o: pci.c
libdrivers_a-3c509.o: 3c509.c
libdrivers_a-3c595.o: 3c595.c
libdrivers_a-3c90x.o: 3c90x.c
libdrivers_a-cs89x0.o: cs89x0.c
libdrivers_a-depca.o: depca.c
libdrivers_a-eepro100.o: eepro100.c
libdrivers_a-epic100.o: epic100.c
libdrivers_a-i82586.o: i82586.c
libdrivers_a-lance.o: lance.c
libdrivers_a-ns8390.o: ns8390.c
libdrivers_a-ntulip.o: ntulip.c
libdrivers_a-otulip.o: otulip.c
libdrivers_a-rtl8139.o: rtl8139.c
libdrivers_a-sk_g16.o: sk_g16.c
libdrivers_a-smc9000.o: smc9000.c
@ -292,9 +298,11 @@ distclean-tags:
maintainer-clean-tags:
@AMDEP@include $(DEPDIR)/libdrivers_a-3c509.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-3c595.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-3c90x.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-config.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-cs89x0.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-depca.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-eepro100.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-epic100.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-fsys_tftp.Po
@ -303,7 +311,7 @@ maintainer-clean-tags:
@AMDEP@include $(DEPDIR)/libdrivers_a-main.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-misc.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-ns8390.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-ntulip.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-otulip.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-pci.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-rtl8139.Po
@AMDEP@include $(DEPDIR)/libdrivers_a-sk_g16.Po
@ -380,6 +388,14 @@ libdrivers_a-3c509.o: 3c509.c
@AMDEP@CCDEPMODE = @CCDEPMODE@
libdrivers_a-3c595.o: 3c595.c
@AMDEP@ source='3c595.c' object='libdrivers_a-3c595.o' libtool=no @AMDEPBACKSLASH@
@AMDEP@ depfile='$(DEPDIR)/libdrivers_a-3c595.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-3c595.TPo' @AMDEPBACKSLASH@
@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-3c595.o `test -f 3c595.c || echo '$(srcdir)/'`3c595.c
@AMDEP@CCDEPMODE = @CCDEPMODE@
libdrivers_a-3c90x.o: 3c90x.c
@AMDEP@ source='3c90x.c' object='libdrivers_a-3c90x.o' libtool=no @AMDEPBACKSLASH@
@AMDEP@ depfile='$(DEPDIR)/libdrivers_a-3c90x.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-3c90x.TPo' @AMDEPBACKSLASH@
@ -396,6 +412,14 @@ libdrivers_a-cs89x0.o: cs89x0.c
@AMDEP@CCDEPMODE = @CCDEPMODE@
libdrivers_a-depca.o: depca.c
@AMDEP@ source='depca.c' object='libdrivers_a-depca.o' libtool=no @AMDEPBACKSLASH@
@AMDEP@ depfile='$(DEPDIR)/libdrivers_a-depca.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-depca.TPo' @AMDEPBACKSLASH@
@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-depca.o `test -f depca.c || echo '$(srcdir)/'`depca.c
@AMDEP@CCDEPMODE = @CCDEPMODE@
libdrivers_a-eepro100.o: eepro100.c
@AMDEP@ source='eepro100.c' object='libdrivers_a-eepro100.o' libtool=no @AMDEPBACKSLASH@
@AMDEP@ depfile='$(DEPDIR)/libdrivers_a-eepro100.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-eepro100.TPo' @AMDEPBACKSLASH@
@ -436,11 +460,11 @@ libdrivers_a-ns8390.o: ns8390.c
@AMDEP@CCDEPMODE = @CCDEPMODE@
libdrivers_a-ntulip.o: ntulip.c
@AMDEP@ source='ntulip.c' object='libdrivers_a-ntulip.o' libtool=no @AMDEPBACKSLASH@
@AMDEP@ depfile='$(DEPDIR)/libdrivers_a-ntulip.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-ntulip.TPo' @AMDEPBACKSLASH@
libdrivers_a-otulip.o: otulip.c
@AMDEP@ source='otulip.c' object='libdrivers_a-otulip.o' libtool=no @AMDEPBACKSLASH@
@AMDEP@ depfile='$(DEPDIR)/libdrivers_a-otulip.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-otulip.TPo' @AMDEPBACKSLASH@
@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-ntulip.o `test -f ntulip.c || echo '$(srcdir)/'`ntulip.c
$(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-otulip.o `test -f otulip.c || echo '$(srcdir)/'`otulip.c
@AMDEP@CCDEPMODE = @CCDEPMODE@
@ -594,10 +618,10 @@ $(3c509_drivers): %.o: 3c509.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
#$(3c59x_drivers): 3c59x.c 3c509.h
#$(3c59x_drivers): %.o: 3c59x.c
# $(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
# $(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(3c595_drivers): 3c595.c 3c595.h
$(3c595_drivers): %.o: 3c595.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(3c90x_drivers): 3c90x.c
$(3c90x_drivers): %.o: 3c90x.c
@ -609,6 +633,11 @@ $(cs89x0_drivers): %.o: cs89x0.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(depca_drivers): depca.c
$(depca_drivers): %.o: depca.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(eepro100_drivers): eepro100.c
$(eepro100_drivers): %.o: eepro100.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
@ -624,8 +653,8 @@ $(lance_drivers): %.o: lance.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(ntulip_drivers): ntulip.c
$(ntulip_drivers): %.o: ntulip.c
$(tulip_drivers): tulip.c
$(tulip_drivers): %.o: tulip.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
@ -649,8 +678,8 @@ $(tiara_drivers): %.o: tiara.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(tulip_drivers): tulip.c tulip.h
$(tulip_drivers): %.o: tulip.c
$(otulip_drivers): otulip.c otulip.h
$(otulip_drivers): %.o: otulip.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<

View file

@ -43,6 +43,12 @@ drivers at the same time.
3Com529 == MCA 3c509
--enable-3c529
3Com590
--enable-3c590
3Com595
--enable-3c595
3Com90x
--enable-3c90x
@ -54,6 +60,9 @@ Crystal Semiconductor CS89x0
a more aggressive probing algorithm. This might be neccessary after
a soft-reset of the NIC.
Digital DE100 and DE200
--enable-depca
Intel Etherexpress Pro/100
--enable-eepro100
@ -64,12 +73,15 @@ EXOS205
--enable-exos205
Lance PCI PCNet/32
--enable-lancepci
--enable-lance
Linksys LNE100TX and other NICs using this Tulip clone chip
Netgear FA310TX and other NICs using this Tulip clone chip
Tulip clones based on the Macronix 987x5
--enable-ntulip
Tulip-Fast
Tulip+
Tulip 21142
--enable-tulip
NE1000/2000 and clones (ISA)
--enable-ne
@ -85,7 +97,7 @@ Winbond 86C940
Compex RL2000
KTI ET32P2
NetVin 5000SC
--enable-nepci
--enable-ns8390
--enable-compex-rl2000-fix
If you have a Compex RL2000 PCI 32-bit (11F6:1401), and the probe
hangs in "Probing...[NE*000/PCI]", try enabling this fix... it
@ -98,6 +110,7 @@ Racal-Interlan NI6510
--enable-ni6510
Realtek 8139
SMC 1211
--enable-rtl8139
Schneider and Koch G16
@ -112,7 +125,7 @@ Tiara, Fujitsu Lancard
--enable-tiara
Old base driver for Tulip clones
--enable-tulip
--enable-otulip
Rhine-I, e.g. D-Link DFE-530TX
Rhine-II

View file

@ -1,77 +0,0 @@
#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

143
netboot/cards.h Normal file
View file

@ -0,0 +1,143 @@
#ifndef CARDS_H
#define CARDS_H
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* your option) any later version.
*/
#include "nic.h"
/* OK, this is how the PCI support hack works: if pci.h is included before
* this file is included, assume that the driver supports PCI. This means that
* this file is usually included last. */
#ifdef PCI_H
#define PCI_ARG(x) ,x
#else
#define PCI_ARG(x)
#endif
#ifdef INCLUDE_WD
extern struct nic *wd_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_3C503
extern struct nic *t503_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_VIA_RHINE
extern struct nic *rhine_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_NE
extern struct nic *ne_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_NS8390
extern struct nic *nepci_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_3C509
extern struct nic *t509_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_3C529
extern struct nic *t529_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_3C90X
extern struct nic *a3c90x_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_EEPRO100
extern struct nic *eepro100_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_EPIC100
extern struct nic *epic100_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_OTULIP
extern struct nic *otulip_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_TULIP
extern struct nic *tulip_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_CS89X0
extern struct nic *cs89x0_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_LANCE
extern struct nic *lancepci_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_NE2100
extern struct nic *ne2100_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_NI6510
extern struct nic *ni6510_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_SK_G16
extern struct nic *SK_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_3C507
extern struct nic *t507_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_NI5210
extern struct nic *ni5210_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_EXOS205
extern struct nic *exos205_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_SMC9000
extern struct nic *smc9000_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_TIARA
extern struct nic *tiara_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_DEPCA
extern struct nic *depca_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_RTL8139
extern struct nic *rtl8139_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#endif /* CARDS_H */

View file

@ -17,27 +17,28 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Based on "src/config.c" in etherboot-4.4.2. Some parts are stolen
from "include/linux/pci.h" in linux-2.2.14. */
/* Based on "src/config.c" in etherboot-4.5.8. */
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* your option) any later version.
*/
#include "etherboot.h"
#include "nic.h"
#include "netboot_config.h"
struct pci_device; /* for the probe prototype */
#undef INCLUDE_PCI
#if defined(INCLUDE_NEPCI) || defined(INCLUDE_EEPRO100) || defined(INCLUDE_LANCEPCI) || defined(INCLUDE_EPIC100) || defined(INCLUDE_TULIP) || defined(INCLUDE_NTULIP) || defined(INCLUDE_3C90X) || defined(INCLUDE_RTL8139) || defined(INCLUDE_VIA_RHINE) || defined(INCLUDE_3C59X)
#if defined(INCLUDE_NS8390) || defined(INCLUDE_EEPRO100) || defined(INCLUDE_LANCE) || defined(INCLUDE_EPIC100) || defined(INCLUDE_TULIP) || defined(INCLUDE_OTULIP) || defined(INCLUDE_3C90X) || defined(INCLUDE_RTL8139) || defined(INCLUDE_VIA_RHINE)
/* || others later */
#if defined(ETHERBOOT32) /* only for 32 bit machines */
#define INCLUDE_PCI
/*#include <linux/pci.h>*/
#include "pci.h"
static unsigned short pci_ioaddrs[16];
static struct pci_device pci_nic_list[] = {
#ifdef INCLUDE_NEPCI
#ifdef INCLUDE_NS8390
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029,
"Realtek 8029", 0, 0, 0},
{ PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940,
@ -85,17 +86,17 @@ static struct pci_device pci_nic_list[] = {
{ PCI_VENDOR_ID_SMC, PCI_DEVICE_ID_SMC_EPIC100,
"SMC EtherPowerII", 0, 0, 0},
#endif
#ifdef INCLUDE_LANCEPCI
#ifdef INCLUDE_LANCE
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
"AMD Lance/PCI", 0, 0, 0},
#endif
#ifdef INCLUDE_RTL8139
#ifdef INCLUDE_RTL8139
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
"Realtek 8139", 0, 0, 0},
{ PCI_VENDOR_ID_SMC_1211, PCI_DEVICE_ID_SMC_1211,
"SMC EZ10/100", 0, 0, 0},
#endif
#ifdef INCLUDE_TULIP
#ifdef INCLUDE_OTULIP
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
"Digital Tulip", 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
@ -105,7 +106,7 @@ static struct pci_device pci_nic_list[] = {
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
"Digital Tulip 21142", 0, 0, 0},
#endif
#ifdef INCLUDE_NTULIP
#ifdef INCLUDE_TULIP
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
"Digital Tulip", 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
@ -121,163 +122,33 @@ static struct pci_device pci_nic_list[] = {
{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_DEC_TULIP,
"Netgear FA310TX", 0, 0, 0},
#endif
#ifdef INCLUDE_VIA_RHINE
#ifdef INCLUDE_VIA_RHINE
{ PCI_VENDOR_ID_VIATEC, PCI_DEVICE_ID_VIA_RHINE_I,
"VIA 3043", 0, 0, 0},
{ PCI_VENDOR_ID_VIATEC, PCI_DEVICE_ID_VIA_86C100A,
"VIA 86C100A", 0, 0, 0},
#endif
#ifdef INCLUDE_3C59X
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C590,
"3c590 Vortex 10Mbps", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595TX,
"3c595 Vortex 100baseTX", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595T4,
"3c595 Vortex 100baseT4", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVIVE_ID_3COM_3C595MII,
"3c595 Vortex 100base-MII", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900TPO,
"3c900 Boomerang 10baseT", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900COMBO,
"3c900 Boomerang 10Mbps/Combo", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905TX,
"3c905 Boomerang 100baseTx", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905T4,
"3c905 Boomerang 100baseT4", 0, 0, 0},
#endif
/* other PCI NICs go here */
{0,}
{0, 0, NULL, 0, 0, 0}
};
#endif /* ETHERBOOT32 */
#endif /* INCLUDE_*PCI */
#include "cards.h"
struct dispatch_table
{
char *nic_name;
const char *nic_name;
#ifdef INCLUDE_PCI
struct nic *(*eth_probe)(struct nic *, unsigned short *,
struct pci_device *);
#else
struct nic *(*eth_probe)(struct nic *, unsigned short *);
#endif /* INCLUDE_PCI */
unsigned short *probe_ioaddrs; /* for probe overrides */
};
#ifdef INCLUDE_WD
extern struct nic *wd_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_3C503
extern struct nic *t503_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_VIA_RHINE
extern struct nic *rhine_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_NE
extern struct nic *ne_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_NEPCI
extern struct nic *nepci_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_3C509
extern struct nic *t509_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_3C529
extern struct nic *t529_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_3C90X
extern struct nic *a3c90x_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_EEPRO100
extern struct nic *eepro100_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_EPIC100
extern struct nic *epic100_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_TULIP
extern struct nic *tulip_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_NTULIP
extern struct nic *ntulip_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_CS89x0
extern struct nic *cs89x0_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_LANCEPCI
extern struct nic *lancepci_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_NE2100
extern struct nic *ne2100_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_NI6510
extern struct nic *ni6510_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_SK_G16
extern struct nic *SK_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_3C507
extern struct nic *t507_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_NI5210
extern struct nic *ni5210_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_EXOS205
extern struct nic *exos205_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_SMC9000
extern struct nic *smc9000_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_TIARA
extern struct nic *tiara_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_RTL8139
extern struct nic *rtl8139_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
#ifdef INCLUDE_3C59X
extern struct nic *VX_probe(struct nic *, unsigned short *,
struct pci_device *);
#endif
/*
* NIC probing is in order of appearance in this table.
* If for some reason you want to change the order,
@ -312,13 +183,13 @@ static struct dispatch_table NIC[] =
#ifdef INCLUDE_EPIC100
{ "EPIC100", epic100_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_OTULIP
{ "OTulip", otulip_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_TULIP
{ "Tulip", tulip_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_NTULIP
{ "NTulip", ntulip_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_CS89x0
#ifdef INCLUDE_CS89X0
{ "CS89x0", cs89x0_probe, 0 },
#endif
#ifdef INCLUDE_NE2100
@ -345,17 +216,17 @@ static struct dispatch_table NIC[] =
#ifdef INCLUDE_TIARA
{ "TIARA", tiara_probe, 0 },
#endif
#ifdef INCLUDE_NEPCI
#ifdef INCLUDE_DEPCA
{ "DEPCA", depca_probe, 0 },
#endif
#ifdef INCLUDE_NS8390
{ "NE2000/PCI", nepci_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_LANCEPCI
#ifdef INCLUDE_LANCE
{ "LANCE/PCI", lancepci_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_VIA_RHINE
#ifdef INCLUDE_VIA_RHINE
{ "VIA 86C100", rhine_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_3C59X
{ "VorTex/PCI", VX_probe, pci_ioaddrs },
#endif
/* this entry must always be last to mark the end of list */
{ 0, 0, 0 }
@ -368,16 +239,16 @@ static int eth_dummy(struct nic *nic)
return (0);
}
char packet[ETH_MAX_PACKET];
static char packet[ETH_MAX_PACKET];
struct nic nic =
{
#ifdef ETHERBOOT32
(void (*)(struct nic *))eth_dummy, /* reset */
eth_dummy, /* poll */
(void (*)(struct nic *, char *,
(void (*)(struct nic *, const char *,
unsigned int, unsigned int,
char *))eth_dummy, /* transmit */
const char *))eth_dummy, /* transmit */
(void (*)(struct nic *))eth_dummy, /* disable */
#endif
/* bcc has problems with complicated casts */
@ -398,7 +269,7 @@ struct nic nic =
0 /* priv_data */
};
#if 0
#ifndef GRUB
void print_config(void)
{
struct dispatch_table *t;
@ -414,7 +285,7 @@ void print_config(void)
printf("[%s]", t->nic_name);
putchar('\n');
}
#endif
#endif /* ! GRUB */
void eth_reset(void)
{
@ -425,24 +296,31 @@ int eth_probe(void)
{
struct pci_device *p;
struct dispatch_table *t;
#ifdef GRUB
static int probed = 0;
#endif /* GRUB */
/* If already probed, don't try to probe it any longer. */
if (probed)
return 1;
#ifdef GRUB
/* If already probed, don't try to probe it any longer. */
if (probed)
return 1;
/* Clear the ready flag. */
network_ready = 0;
/* Clear the ARP table. */
grub_memset ((char *) arptable, 0,
MAX_ARP * sizeof (struct arptable_t));
network_ready = 0;
/* Clear the ARP table. */
grub_memset ((char *) arptable, 0,
MAX_ARP * sizeof (struct arptable_t));
#endif /* GRUB */
p = 0;
#ifdef INCLUDE_PCI
/* In GRUB, the ROM info is initialized here. */
rom = *((struct rom_info *) ROM_INFO_LOCATION);
eth_pci_init(pci_nic_list);
# ifdef GRUB
/* In GRUB, the ROM info is initialized here. */
rom = *((struct rom_info *) ROM_INFO_LOCATION);
# endif /* GRUB */
eth_pci_init(pci_nic_list);
pci_ioaddrs[0] = 0;
pci_ioaddrs[1] = 0;
/* at this point we have a list of possible PCI candidates
@ -458,11 +336,16 @@ int eth_probe(void)
for (t = NIC; t->nic_name != 0; ++t)
{
printf("[%s]", t->nic_name);
if ((*t->eth_probe)(&nic, t->probe_ioaddrs, p))
{
probed = 1;
return (1);
}
#ifdef INCLUDE_PCI
if ((*t->eth_probe)(&nic, t->probe_ioaddrs, p)) {
#else
if ((*t->eth_probe)(&nic, t->probe_ioaddrs)) {
#endif /* INCLUDE_PCI */
#ifdef GRUB
probed = 1;
#endif /* GRUB */
return (1);
}
}
return (0);
}
@ -472,7 +355,7 @@ int eth_poll(void)
return ((*nic.poll)(&nic));
}
void eth_transmit(char *d, unsigned int t, unsigned int s, char *p)
void eth_transmit(const char *d, unsigned int t, unsigned int s, const void *p)
{
(*nic.transmit)(&nic, d, t, s, p);
twiddle();

View file

@ -19,7 +19,7 @@
* 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
@ -30,7 +30,7 @@
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
@ -50,7 +50,7 @@
* 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
@ -60,17 +60,18 @@
the time being, it will only work for Etherboot/32.
* 12
*/
#include "etherboot.h"
#include "nic.h"
#include "cards.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_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;
@ -80,16 +81,13 @@ static unsigned char eth_vendor;
CS89x0 - specific routines
**************************************************************************/
static int inline readreg(portno)
int portno;
static inline int readreg(int portno)
{
outw(portno, eth_nic_base + ADD_PORT);
return inw(eth_nic_base + DATA_PORT);
}
static void inline writereg(portno,value)
int portno;
int value;
static inline void writereg(int portno, int value)
{
outw(portno, eth_nic_base + ADD_PORT);
outw(value, eth_nic_base + DATA_PORT);
@ -100,27 +98,24 @@ static void inline writereg(portno,value)
EEPROM access
**************************************************************************/
static int wait_eeprom_ready()
static int wait_eeprom_ready(void)
{
long tmo = currticks() + 4*TICKS_PER_SEC;
unsigned long tmo = currticks() + 4*TICKS_PER_SEC;
/* 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)
if (currticks() >= tmo)
return -1; }
return 0;
}
static int get_eeprom_data(off,len,buffer)
int off;
int len;
unsigned short *buffer;
static int get_eeprom_data(int off, int len, unsigned short *buffer)
{
int i;
#if defined(EDEBUG)
#ifdef EDEBUG
printf("\ncs: EEPROM data from %x for %x:",off,len);
#endif
for (i = 0; i < len; i++) {
@ -132,23 +127,20 @@ static int get_eeprom_data(off,len,buffer)
if (wait_eeprom_ready() < 0)
return -1;
buffer[i] = readreg(PP_EEData);
#if defined(EDEBUG)
#ifdef EDEBUG
if (!(i%10))
printf("\ncs: ");
printf("%x ", buffer[i]);
#endif
}
#if defined(EDEBUG)
#ifdef EDEBUG
putchar('\n');
#endif
return(0);
}
static int get_eeprom_chksum(off, len, buffer)
int off;
int len;
unsigned short *buffer;
static int get_eeprom_chksum(int off, int len, unsigned short *buffer)
{
int i, cksum;
@ -165,7 +157,7 @@ static int get_eeprom_chksum(off, len, buffer)
Activate all of the available media and probe for network
**************************************************************************/
static void clrline()
static void clrline(void)
{
int i;
@ -175,11 +167,10 @@ static void clrline()
return;
}
static void control_dc_dc(on_not_off)
int on_not_off;
static void control_dc_dc(int on_not_off)
{
unsigned int selfcontrol;
long tmo = currticks() + TICKS_PER_SEC;
unsigned long tmo = currticks() + TICKS_PER_SEC;
/* control the DC to DC convertor in the SelfControl register. */
selfcontrol = HCB1_ENBL; /* Enable the HCB1 bit as an output */
@ -188,19 +179,19 @@ static void control_dc_dc(on_not_off)
else
selfcontrol &= ~HCB1;
writereg(PP_SelfCTL, selfcontrol);
/* Wait for the DC/DC converter to power up - 1000ms */
while (currticks() - tmo < 0);
while (currticks() < tmo);
return;
}
static int detect_tp()
static int detect_tp(void)
{
long tmo;
unsigned 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
@ -214,8 +205,8 @@ static int detect_tp()
/* Delay for the hardware to work out if the TP cable is
present - 150ms */
for (tmo = currticks() + 4; currticks() - tmo < 0; );
for (tmo = currticks() + 4; currticks() < tmo; );
if ((readreg(PP_LineST) & LINK_OK) == 0)
return 0;
@ -248,7 +239,7 @@ static int send_test_pkt(struct nic *nic)
0, 46, /*A 46 in network order */
0, 0, /*DSAP=0 & SSAP=0 fields */
0xf3,0 /*Control (Test Req+P bit set)*/ };
long tmo;
unsigned long tmo;
writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON);
@ -261,7 +252,7 @@ static int send_test_pkt(struct nic *nic)
/* 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)
if (currticks() >= tmo)
return(0);
/* Write the contents of the packet */
@ -270,8 +261,8 @@ static int send_test_pkt(struct nic *nic)
printf(" sending test packet ");
/* wait a couple of timer ticks for packet to be received */
for (tmo = currticks() + 2; currticks() - tmo < 0; );
for (tmo = currticks() + 2; currticks() < tmo; );
if ((readreg(PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
printf("succeeded");
return 1;
@ -311,10 +302,10 @@ static int detect_bnc(struct nic *nic)
ETH_RESET - Reset adapter
***************************************************************************/
void cs89x0_reset(struct nic *nic)
static void cs89x0_reset(struct nic *nic)
{
int i;
long reset_tmo;
unsigned long reset_tmo;
if(eth_vendor!=VENDOR_CS89x0)
return;
@ -322,8 +313,7 @@ void cs89x0_reset(struct nic *nic)
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(); );
for (reset_tmo = currticks() + 2; currticks() < reset_tmo; );
if (eth_cs_type != CS8900) {
/* Hardware problem requires PNP registers to be reconfigured
@ -337,11 +327,11 @@ void cs89x0_reset(struct nic *nic)
outw(PP_CS8920_ISAMemB, eth_nic_base + ADD_PORT);
outb((eth_mem_start >> 8) & 0xff, eth_nic_base + DATA_PORT);
outb((eth_mem_start >> 24) & 0xff, eth_nic_base + DATA_PORT + 1); } }
/* Wait until the chip is reset */
for (reset_tmo = currticks() + 2;
(readreg(PP_SelfST) & INIT_DONE) == 0 &&
currticks() - reset_tmo < 0; );
currticks() < reset_tmo; );
/* disable interrupts and memory accesses */
writereg(PP_BusCTL, 0);
@ -376,12 +366,12 @@ ETH_TRANSMIT - Transmit a frame
static void cs89x0_transmit(
struct nic *nic,
char *d, /* Destination */
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
const char *p) /* Packet */
{
long tmo;
unsigned long tmo;
int sr;
if(eth_vendor!=VENDOR_CS89x0)
@ -401,7 +391,7 @@ retry:
if ((readreg(PP_BusST) & READY_FOR_TX_NOW) == 0) {
/* Oops... this should not happen! */
printf("cs: unable to send packet; retrying...\n");
for (tmo = currticks() + 5*TICKS_PER_SEC; currticks() - tmo < 0; );
for (tmo = currticks() + 5*TICKS_PER_SEC; currticks() < tmo; );
cs89x0_reset(nic);
goto retry; }
@ -416,8 +406,8 @@ retry:
/* wait for transfer to succeed */
for (tmo = currticks()+5*TICKS_PER_SEC;
(s = readreg(PP_TxEvent)&~0x1F) == 0 && currticks() - tmo < 0;
twiddle());
(s = readreg(PP_TxEvent)&~0x1F) == 0 && currticks() < tmo;)
/* nothing */ ;
if ((s & TX_SEND_OK_BITS) != TX_OK) {
printf("\ntransmission error 0x%x\n", s);
}
@ -460,12 +450,12 @@ 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
#ifdef CS_SCAN
CS_SCAN,
#else /* use "conservative" default values for autoprobing */
#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 */
/* if that did not work, then be more aggressive */
0x301,0x321,0x341,0x201,0x221,0x241,
0x261,0x281,0x2a1,0x2c1,0x2e1,
#endif
@ -503,7 +493,7 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
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("\ncs: no EEPROM...\n");
@ -530,12 +520,12 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
/* 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 */
@ -558,7 +548,7 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
eth_irq = i; }
/* Retrieve and print the ethernet address. */
for (i=0; i<ETHER_ADDR_SIZE; i++) {
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 ? ":" : "\n"); }
@ -580,13 +570,13 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
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 |
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\n");
error:
writereg(PP_LineCTL, readreg(PP_LineCTL) &
writereg(PP_LineCTL, readreg(PP_LineCTL) &
~(SERIAL_TX_ON | SERIAL_RX_ON));
outw(PP_ChipID, eth_nic_base + ADD_PORT);
continue;
@ -596,7 +586,7 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
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:

View file

@ -78,7 +78,7 @@
#define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */
#ifdef IBMEIPKT
#ifdef IBMEIPKT
#define EISA_ID_SIG 0x4D24 /* IBM */
#define PART_NO_SIG 0x1010 /* IBM */
#define MONGOOSE_BIT 0x0000 /* IBM */
@ -343,7 +343,7 @@
/* for bios scan */
/* */
#ifdef CSDEBUG
#ifdef CSDEBUG
/* use these values for debugging bios scan */
#define BIOS_START_SEG 0x00000
#define BIOS_OFFSET_INC 0x0010
@ -369,7 +369,7 @@
#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 IMM_BIT 0x0040 /* ignore missing media */
#define ADAPTER_CNF_OFFSET (AUTO_NEG_CNF_OFFSET + 2)
#define A_CNF_10B_T 0x0001
@ -417,8 +417,8 @@
#define DMA_SIZE (16*1024) /* Size of dma buffer - 16k */
#define CS8900 0x0000
#define CS8920 0x4000
#define CS8920M 0x6000
#define CS8920 0x4000
#define CS8920M 0x6000
#define REVISON_BITS 0x1F00
#define EEVER_NUMBER 0x12
#define CHKSUM_LEN 0x14

26
netboot/cs89x0.txt Normal file
View file

@ -0,0 +1,26 @@
Permission is granted to distribute the enclosed cs89x0.[ch] driver
only in conjunction with the Etherboot package. The code is
ordinarily distributed under the GPL.
Russ Nelson, January 2000
CREDITS
I want to thank
Mike Cruse <mcruse@cti-ltd.com>
for providing an evaluation NIC and for sponsoring the
development of this driver.
Randall Sears <sears@crystal.cirrus.com>
Deva Bodas <bodas@crystal.cirrus.com>
Andreas Kraemer <akraemer@crystal.cirrus.com>
Wolfgang Krause <100303.2673@compuserve.com>
for excellent technical support and for providing the required
programming information. I appreciate Crystal Semiconductor's
commitment towards free software.
Russell Nelson <nelson@crynwr.com>
for writing the Linux device driver for the CS89x0
chipset. Russel's code is very well designed and simplified my
job a lot.

698
netboot/depca.c Normal file
View file

@ -0,0 +1,698 @@
/* depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
Written 1994, 1995 by David C. Davies.
Copyright 1994 David C. Davies
and
United States Government
(as represented by the Director, National Security Agency).
Copyright 1995 Digital Equipment Corporation.
This software may be used and distributed according to the terms of
the GNU Public License, incorporated herein by reference.
This driver is written for the Digital Equipment Corporation series
of DEPCA and EtherWORKS ethernet cards:
DEPCA (the original)
DE100
DE101
DE200 Turbo
DE201 Turbo
DE202 Turbo (TP BNC)
DE210
DE422 (EISA)
The driver has been tested on DE100, DE200 and DE202 cards in a
relatively busy network. The DE422 has been tested a little.
This driver will NOT work for the DE203, DE204 and DE205 series of
cards, since they have a new custom ASIC in place of the AMD LANCE
chip. See the 'ewrk3.c' driver in the Linux source tree for running
those cards.
I have benchmarked the driver with a DE100 at 595kB/s to (542kB/s from)
a DECstation 5000/200.
The author may be reached at davies@maniac.ultranet.com
=========================================================================
The driver was originally based on the 'lance.c' driver from Donald
Becker which is included with the standard driver distribution for
linux. V0.4 is a complete re-write with only the kernel interface
remaining from the original code.
1) Lance.c code in /linux/drivers/net/
2) "Ethernet/IEEE 802.3 Family. 1992 World Network Data Book/Handbook",
AMD, 1992 [(800) 222-9323].
3) "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)",
AMD, Pub. #17881, May 1993.
4) "Am79C960 PCnet-ISA(tm), Single-Chip Ethernet Controller for ISA",
AMD, Pub. #16907, May 1992
5) "DEC EtherWORKS LC Ethernet Controller Owners Manual",
Digital Equipment corporation, 1990, Pub. #EK-DE100-OM.003
6) "DEC EtherWORKS Turbo Ethernet Controller Owners Manual",
Digital Equipment corporation, 1990, Pub. #EK-DE200-OM.003
7) "DEPCA Hardware Reference Manual", Pub. #EK-DEPCA-PR
Digital Equipment Corporation, 1989
8) "DEC EtherWORKS Turbo_(TP BNC) Ethernet Controller Owners Manual",
Digital Equipment corporation, 1991, Pub. #EK-DE202-OM.001
Peter Bauer's depca.c (V0.5) was referred to when debugging V0.1 of this
driver.
The original DEPCA card requires that the ethernet ROM address counter
be enabled to count and has an 8 bit NICSR. The ROM counter enabling is
only done when a 0x08 is read as the first address octet (to minimise
the chances of writing over some other hardware's I/O register). The
NICSR accesses have been changed to byte accesses for all the cards
supported by this driver, since there is only one useful bit in the MSB
(remote boot timeout) and it is not used. Also, there is a maximum of
only 48kB network RAM for this card. My thanks to Torbjorn Lindh for
help debugging all this (and holding my feet to the fire until I got it
right).
The DE200 series boards have on-board 64kB RAM for use as a shared
memory network buffer. Only the DE100 cards make use of a 2kB buffer
mode which has not been implemented in this driver (only the 32kB and
64kB modes are supported [16kB/48kB for the original DEPCA]).
At the most only 2 DEPCA cards can be supported on the ISA bus because
there is only provision for two I/O base addresses on each card (0x300
and 0x200). The I/O address is detected by searching for a byte sequence
in the Ethernet station address PROM at the expected I/O address for the
Ethernet PROM. The shared memory base address is 'autoprobed' by
looking for the self test PROM and detecting the card name. When a
second DEPCA is detected, information is placed in the base_addr
variable of the next device structure (which is created if necessary),
thus enabling ethif_probe initialization for the device. More than 2
EISA cards can be supported, but care will be needed assigning the
shared memory to ensure that each slot has the correct IRQ, I/O address
and shared memory address assigned.
************************************************************************
NOTE: If you are using two ISA DEPCAs, it is important that you assign
the base memory addresses correctly. The driver autoprobes I/O 0x300
then 0x200. The base memory address for the first device must be less
than that of the second so that the auto probe will correctly assign the
I/O and memory addresses on the same card. I can't think of a way to do
this unambiguously at the moment, since there is nothing on the cards to
tie I/O and memory information together.
I am unable to test 2 cards together for now, so this code is
unchecked. All reports, good or bad, are welcome.
************************************************************************
The board IRQ setting must be at an unused IRQ which is auto-probed
using Donald Becker's autoprobe routines. DEPCA and DE100 board IRQs are
{2,3,4,5,7}, whereas the DE200 is at {5,9,10,11,15}. Note that IRQ2 is
really IRQ9 in machines with 16 IRQ lines.
No 16MB memory limitation should exist with this driver as DMA is not
used and the common memory area is in low memory on the network card (my
current system has 20MB and I've not had problems yet).
The ability to load this driver as a loadable module has been added. To
utilise this ability, you have to do <8 things:
0) have a copy of the loadable modules code installed on your system.
1) copy depca.c from the /linux/drivers/net directory to your favourite
temporary directory.
2) if you wish, edit the source code near line 1530 to reflect the I/O
address and IRQ you're using (see also 5).
3) compile depca.c, but include -DMODULE in the command line to ensure
that the correct bits are compiled (see end of source code).
4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
kernel with the depca configuration turned off and reboot.
5) insmod depca.o [irq=7] [io=0x200] [mem=0xd0000] [adapter_name=DE100]
[Alan Cox: Changed the code to allow command line irq/io assignments]
[Dave Davies: Changed the code to allow command line mem/name
assignments]
6) run the net startup bits for your eth?? interface manually
(usually /etc/rc.inet[12] at boot time).
7) enjoy!
Note that autoprobing is not allowed in loadable modules - the system is
already up and running and you're messing with interrupts.
To unload a module, turn off the associated interface
'ifconfig eth?? down' then 'rmmod depca'.
To assign a base memory address for the shared memory when running as a
loadable module, see 5 above. To include the adapter name (if you have
no PROM but know the card name) also see 5 above. Note that this last
option will not work with kernel built-in depca's.
The shared memory assignment for a loadable module makes sense to avoid
the 'memory autoprobe' picking the wrong shared memory (for the case of
2 depca's in a PC).
************************************************************************
Support for MCA EtherWORKS cards added 11-3-98.
Verified to work with up to 2 DE212 cards in a system (although not
fully stress-tested).
Currently known bugs/limitations:
Note: with the MCA stuff as a module, it trusts the MCA configuration,
not the command line for IRQ and memory address. You can
specify them if you want, but it will throw your values out.
You still have to pass the IO address it was configured as
though.
************************************************************************
TO DO:
------
Revision History
----------------
Version Date Description
0.1 25-jan-94 Initial writing.
0.2 27-jan-94 Added LANCE TX hardware buffer chaining.
0.3 1-feb-94 Added multiple DEPCA support.
0.31 4-feb-94 Added DE202 recognition.
0.32 19-feb-94 Tidy up. Improve multi-DEPCA support.
0.33 25-feb-94 Fix DEPCA ethernet ROM counter enable.
Add jabber packet fix from murf@perftech.com
and becker@super.org
0.34 7-mar-94 Fix DEPCA max network memory RAM & NICSR access.
0.35 8-mar-94 Added DE201 recognition. Tidied up.
0.351 30-apr-94 Added EISA support. Added DE422 recognition.
0.36 16-may-94 DE422 fix released.
0.37 22-jul-94 Added MODULE support
0.38 15-aug-94 Added DBR ROM switch in depca_close().
Multi DEPCA bug fix.
0.38axp 15-sep-94 Special version for Alpha AXP Linux V1.0.
0.381 12-dec-94 Added DE101 recognition, fix multicast bug.
0.382 9-feb-95 Fix recognition bug reported by <bkm@star.rl.ac.uk>.
0.383 22-feb-95 Fix for conflict with VESA SCSI reported by
<stromain@alf.dec.com>
0.384 17-mar-95 Fix a ring full bug reported by <bkm@star.rl.ac.uk>
0.385 3-apr-95 Fix a recognition bug reported by
<ryan.niemi@lastfrontier.com>
0.386 21-apr-95 Fix the last fix...sorry, must be galloping senility
0.40 25-May-95 Rewrite for portability & updated.
ALPHA support from <jestabro@amt.tay1.dec.com>
0.41 26-Jun-95 Added verify_area() calls in depca_ioctl() from
suggestion by <heiko@colossus.escape.de>
0.42 27-Dec-95 Add 'mem' shared memory assignment for loadable
modules.
Add 'adapter_name' for loadable modules when no PROM.
Both above from a suggestion by
<pchen@woodruffs121.residence.gatech.edu>.
Add new multicasting code.
0.421 22-Apr-96 Fix alloc_device() bug <jari@markkus2.fimr.fi>
0.422 29-Apr-96 Fix depca_hw_init() bug <jari@markkus2.fimr.fi>
0.423 7-Jun-96 Fix module load bug <kmg@barco.be>
0.43 16-Aug-96 Update alloc_device() to conform to de4x5.c
0.44 1-Sep-97 Fix *_probe() to test check_region() first - bug
reported by <mmogilvi@elbert.uccs.edu>
0.45 3-Nov-98 Added support for MCA EtherWORKS (DE210/DE212) cards
by <tymm@computer.org>
0.451 5-Nov-98 Fixed mca stuff cuz I'm a dummy. <tymm@computer.org>
0.5 14-Nov-98 Re-spin for 2.1.x kernels.
0.51 27-Jun-99 Correct received packet length for CRC from
report by <worm@dkik.dk>
=========================================================================
*/
#include "etherboot.h"
#include "nic.h"
#include "cards.h"
/*
** I/O addresses. Note that the 2k buffer option is not supported in
** this driver.
*/
#define DEPCA_NICSR ioaddr+0x00 /* Network interface CSR */
#define DEPCA_RBI ioaddr+0x02 /* RAM buffer index (2k buffer mode) */
#define DEPCA_DATA ioaddr+0x04 /* LANCE registers' data port */
#define DEPCA_ADDR ioaddr+0x06 /* LANCE registers' address port */
#define DEPCA_HBASE ioaddr+0x08 /* EISA high memory base address reg. */
#define DEPCA_PROM ioaddr+0x0c /* Ethernet address ROM data port */
#define DEPCA_CNFG ioaddr+0x0c /* EISA Configuration port */
#define DEPCA_RBSA ioaddr+0x0e /* RAM buffer starting address (2k buff.) */
/*
** These are LANCE registers addressable through DEPCA_ADDR
*/
#define CSR0 0
#define CSR1 1
#define CSR2 2
#define CSR3 3
/*
** NETWORK INTERFACE CSR (NI_CSR) bit definitions
*/
#define TO 0x0100 /* Time Out for remote boot */
#define SHE 0x0080 /* SHadow memory Enable */
#define BS 0x0040 /* Bank Select */
#define BUF 0x0020 /* BUFfer size (1->32k, 0->64k) */
#define RBE 0x0010 /* Remote Boot Enable (1->net boot) */
#define AAC 0x0008 /* Address ROM Address Counter (1->enable) */
#define _128KB 0x0008 /* 128kB Network RAM (1->enable) */
#define IM 0x0004 /* Interrupt Mask (1->mask) */
#define IEN 0x0002 /* Interrupt tristate ENable (1->enable) */
#define LED 0x0001 /* LED control */
/*
** Control and Status Register 0 (CSR0) bit definitions
*/
#define ERR 0x8000 /* Error summary */
#define BABL 0x4000 /* Babble transmitter timeout error */
#define CERR 0x2000 /* Collision Error */
#define MISS 0x1000 /* Missed packet */
#define MERR 0x0800 /* Memory Error */
#define RINT 0x0400 /* Receiver Interrupt */
#define TINT 0x0200 /* Transmit Interrupt */
#define IDON 0x0100 /* Initialization Done */
#define INTR 0x0080 /* Interrupt Flag */
#define INEA 0x0040 /* Interrupt Enable */
#define RXON 0x0020 /* Receiver on */
#define TXON 0x0010 /* Transmitter on */
#define TDMD 0x0008 /* Transmit Demand */
#define STOP 0x0004 /* Stop */
#define STRT 0x0002 /* Start */
#define INIT 0x0001 /* Initialize */
#define INTM 0xff00 /* Interrupt Mask */
#define INTE 0xfff0 /* Interrupt Enable */
/*
** CONTROL AND STATUS REGISTER 3 (CSR3)
*/
#define BSWP 0x0004 /* Byte SWaP */
#define ACON 0x0002 /* ALE control */
#define BCON 0x0001 /* Byte CONtrol */
/*
** Initialization Block Mode Register
*/
#define PROM 0x8000 /* Promiscuous Mode */
#define EMBA 0x0080 /* Enable Modified Back-off Algorithm */
#define INTL 0x0040 /* Internal Loopback */
#define DRTY 0x0020 /* Disable Retry */
#define COLL 0x0010 /* Force Collision */
#define DTCR 0x0008 /* Disable Transmit CRC */
#define LOOP 0x0004 /* Loopback */
#define DTX 0x0002 /* Disable the Transmitter */
#define DRX 0x0001 /* Disable the Receiver */
/*
** Receive Message Descriptor 1 (RMD1) bit definitions.
*/
#define R_OWN 0x80000000 /* Owner bit 0 = host, 1 = lance */
#define R_ERR 0x4000 /* Error Summary */
#define R_FRAM 0x2000 /* Framing Error */
#define R_OFLO 0x1000 /* Overflow Error */
#define R_CRC 0x0800 /* CRC Error */
#define R_BUFF 0x0400 /* Buffer Error */
#define R_STP 0x0200 /* Start of Packet */
#define R_ENP 0x0100 /* End of Packet */
/*
** Transmit Message Descriptor 1 (TMD1) bit definitions.
*/
#define T_OWN 0x80000000 /* Owner bit 0 = host, 1 = lance */
#define T_ERR 0x4000 /* Error Summary */
#define T_ADD_FCS 0x2000 /* More the 1 retry needed to Xmit */
#define T_MORE 0x1000 /* >1 retry to transmit packet */
#define T_ONE 0x0800 /* 1 try needed to transmit the packet */
#define T_DEF 0x0400 /* Deferred */
#define T_STP 0x02000000 /* Start of Packet */
#define T_ENP 0x01000000 /* End of Packet */
#define T_FLAGS 0xff000000 /* TX Flags Field */
/*
** Transmit Message Descriptor 3 (TMD3) bit definitions.
*/
#define TMD3_BUFF 0x8000 /* BUFFer error */
#define TMD3_UFLO 0x4000 /* UnderFLOw error */
#define TMD3_RES 0x2000 /* REServed */
#define TMD3_LCOL 0x1000 /* Late COLlision */
#define TMD3_LCAR 0x0800 /* Loss of CARrier */
#define TMD3_RTRY 0x0400 /* ReTRY error */
/*
** EISA configuration Register (CNFG) bit definitions
*/
#define TIMEO 0x0100 /* 0:2.5 mins, 1: 30 secs */
#define REMOTE 0x0080 /* Remote Boot Enable -> 1 */
#define IRQ11 0x0040 /* Enable -> 1 */
#define IRQ10 0x0020 /* Enable -> 1 */
#define IRQ9 0x0010 /* Enable -> 1 */
#define IRQ5 0x0008 /* Enable -> 1 */
#define BUFF 0x0004 /* 0: 64kB or 128kB, 1: 32kB */
#define PADR16 0x0002 /* RAM on 64kB boundary */
#define PADR17 0x0001 /* RAM on 128kB boundary */
/*
** Miscellaneous
*/
#define HASH_TABLE_LEN 64 /* Bits */
#define HASH_BITS 0x003f /* 6 LS bits */
#define MASK_INTERRUPTS 1
#define UNMASK_INTERRUPTS 0
#define EISA_EN 0x0001 /* Enable EISA bus buffers */
#define EISA_ID iobase+0x0080 /* ID long word for EISA card */
#define EISA_CTRL iobase+0x0084 /* Control word for EISA card */
/*
** Recognised commands for the driver
*/
#define DEPCA_GET_HWADDR 0x01 /* Get the hardware address */
#define DEPCA_SET_HWADDR 0x02 /* Get the hardware address */
#define DEPCA_SET_PROM 0x03 /* Set Promiscuous Mode */
#define DEPCA_CLR_PROM 0x04 /* Clear Promiscuous Mode */
#define DEPCA_SAY_BOO 0x05 /* Say "Boo!" to the kernel log file */
#define DEPCA_GET_MCA 0x06 /* Get a multicast address */
#define DEPCA_SET_MCA 0x07 /* Set a multicast address */
#define DEPCA_CLR_MCA 0x08 /* Clear a multicast address */
#define DEPCA_MCA_EN 0x09 /* Enable a multicast address group */
#define DEPCA_GET_STATS 0x0a /* Get the driver statistics */
#define DEPCA_CLR_STATS 0x0b /* Zero out the driver statistics */
#define DEPCA_GET_REG 0x0c /* Get the Register contents */
#define DEPCA_SET_REG 0x0d /* Set the Register contents */
#define DEPCA_DUMP 0x0f /* Dump the DEPCA Status */
#ifdef DEPCA_DEBUG
static int depca_debug = DEPCA_DEBUG;
#else
static int depca_debug = 1;
#endif
#define DEPCA_NDA 0xffe0 /* No Device Address */
/*
** Ethernet PROM defines
*/
#define PROBE_LENGTH 32
#define ETH_PROM_SIG 0xAA5500FFUL
/*
** Set the number of Tx and Rx buffers. Ensure that the memory requested
** here is <= to the amount of shared memory set up by the board switches.
** The number of descriptors MUST BE A POWER OF 2.
**
** total_memory = NUM_RX_DESC*(8+RX_BUFF_SZ) + NUM_TX_DESC*(8+TX_BUFF_SZ)
*/
#define NUM_RX_DESC 8 /* Number of RX descriptors */
#define NUM_TX_DESC 8 /* Number of TX descriptors */
#define RX_BUFF_SZ 1536 /* Buffer size for each Rx buffer */
#define TX_BUFF_SZ 1536 /* Buffer size for each Tx buffer */
#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
/*
** EISA bus defines
*/
#define DEPCA_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */
#define MAX_EISA_SLOTS 16
#define EISA_SLOT_INC 0x1000
/*
** ISA Bus defines
*/
#define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000}
#define DEPCA_IO_PORTS {0x300, 0x200, 0}
#define DEPCA_TOTAL_SIZE 0x10
static short mem_chkd = 0;
/*
** Adapter ID for the MCA EtherWORKS DE210/212 adapter
*/
#define DE212_ID 0x6def
/*
** Name <-> Adapter mapping
*/
#define DEPCA_SIGNATURE {"DEPCA",\
"DE100","DE101",\
"DE200","DE201","DE202",\
"DE210","DE212",\
"DE422",\
""}
static enum {
DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
} adapter;
/*
** Miscellaneous info...
*/
#define DEPCA_STRLEN 16
#define MAX_NUM_DEPCAS 2
/*
** Memory Alignment. Each descriptor is 4 longwords long. To force a
** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
** DESC_ALIGN. ALIGN aligns the start address of the private memory area
** and hence the RX descriptor ring's first entry.
*/
#define ALIGN4 ((u_long)4 - 1) /* 1 longword align */
#define ALIGN8 ((u_long)8 - 1) /* 2 longword (quadword) align */
#define ALIGN ALIGN8 /* Keep the LANCE happy... */
typedef long s32;
typedef unsigned long u32;
typedef unsigned long u_long;
typedef short s16;
typedef unsigned short u16;
typedef unsigned char u8;
typedef char s8;
/*
** The DEPCA Rx and Tx ring descriptors.
*/
struct depca_rx_desc {
volatile s32 base;
s16 buf_length; /* This length is negative 2's complement! */
s16 msg_length; /* This length is "normal". */
};
struct depca_tx_desc {
volatile s32 base;
s16 length; /* This length is negative 2's complement! */
s16 misc; /* Errors and TDR info */
};
#define LA_MASK 0x0000ffff /* LANCE address mask for mapping network RAM
to LANCE memory address space */
/*
** The Lance initialization block, described in databook, in common memory.
*/
struct depca_init {
u16 mode; /* Mode register */
u8 phys_addr[ETHER_ADDR_SIZE]; /* Physical ethernet address */
u8 mcast_table[8]; /* Multicast Hash Table. */
u32 rx_ring; /* Rx ring base pointer & ring length */
u32 tx_ring; /* Tx ring base pointer & ring length */
};
#define DEPCA_PKT_STAT_SZ 16
#define DEPCA_PKT_BIN_SZ 128 /* Should be >=100 unless you
increase DEPCA_PKT_STAT_SZ */
struct depca_private {
char devname[DEPCA_STRLEN]; /* Device Product String */
char adapter_name[DEPCA_STRLEN];/* /proc/ioports string */
char adapter; /* Adapter type */
char mca_slot; /* MCA slot, if MCA else -1 */ struct depca_rx_desc *rx_ring; /* Pointer to start of RX descriptor ring */
struct depca_tx_desc *tx_ring; /* Pointer to start of TX descriptor ring */
struct depca_init init_block;/* Shadow Initialization block */
char *rx_memcpy[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */
char *tx_memcpy[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */
u_long bus_offset; /* (E)ISA bus address offset vs LANCE */
u_long sh_mem; /* Physical start addr of shared mem area */
u_long dma_buffs; /* LANCE Rx and Tx buffers start address. */
int rx_new, tx_new; /* The next free ring entry */
int rx_old, tx_old; /* The ring entries to be free()ed. */
struct { /* Private stats counters */
u32 bins[DEPCA_PKT_STAT_SZ];
u32 unicast;
u32 multicast;
u32 broadcast;
u32 excessive_collisions;
u32 tx_underruns;
u32 excessive_underruns;
} pktStats;
int txRingMask; /* TX ring mask */
int rxRingMask; /* RX ring mask */
s32 rx_rlen; /* log2(rxRingMask+1) for the descriptors */
s32 tx_rlen; /* log2(txRingMask+1) for the descriptors */
};
/*
** The transmit ring full condition is described by the tx_old and tx_new
** pointers by:
** tx_old = tx_new Empty ring
** tx_old = tx_new+1 Full ring
** tx_old+txRingMask = tx_new Full ring (wrapped condition)
*/
#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
lp->tx_old+lp->txRingMask-lp->tx_new:\
lp->tx_old -lp->tx_new-1)
static char name[DEPCA_STRLEN];
static int num_depcas = 0, num_eth = 0;
static int mem=0; /* For loadable module assignment
use insmod mem=0x????? .... */
static char *adapter_name = '\0'; /* If no PROM when loadable module
use insmod adapter_name=DE??? ...
*/
static unsigned short ioaddr = 0;
/*
** Miscellaneous defines...
*/
#define STOP_DEPCA \
outw(CSR0, DEPCA_ADDR);\
outw(STOP, DEPCA_DATA)
/**************************************************************************
RESET - Reset adapter
***************************************************************************/
static void depca_reset(struct nic *nic)
{
#if 0
int i, j, offset, netRAM, mem_len, status = 0;
s16 nicsr;
Address mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
/* put the card in its initial state */
STOP_DEPCA;
nicsr = inb(DEPCA_NICSR);
nicsr = ((nicsr & ~SHE & ~RBE & ~IEN( | IM);
outb(nicsr, DEPCA_NICSR);
if (inw(DEPCA_DATA) == STOP) {
do {
strcpu(name, (adapter_name ? adapter_name : ""));
mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]);
DepcaSignature(name, mem_start);
} while (!mem && mem_base[mem_chkd] && (adapter == unknown));
if ((adapter != unknown) && mem_start) {
;
}
#endif
}
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
static int depca_poll(struct nic *nic)
{
/* return true if there's an ethernet packet ready to read */
/* nic->packet should contain data on return */
/* nic->packetlen should contain length of data */
return 0;
}
/**************************************************************************
TRANSMIT - Transmit a frame
***************************************************************************/
static void depca_transmit(
struct nic *nic,
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
const char *p) /* Packet */
{
/* send the packet to destination */
}
/**************************************************************************
DISABLE - Turn off ethernet interface
***************************************************************************/
static void depca_disable(struct nic *nic)
{
}
/* Return 1 if device present at ioaddr */
static int DevicePresent(void)
{
union {
struct {
u32 a;
u32 b;
} llsig;
char Sig[sizeof(u32) << 1];
} dev;
short siglength = 0;
s8 data;
s16 nicsr;
int i, j;
data = inb(DEPCA_PROM); /* clear counter on DEPCA */
data = inb(DEPCA_PROM); /* read data */
if (data == 0x8) {
nicsr = inb(DEPCA_NICSR);
nicsr |= AAC;
outb(nicsr, DEPCA_NICSR);
}
dev.llsig.a = ETH_PROM_SIG;
dev.llsig.b = ETH_PROM_SIG;
siglength = sizeof(u32) << 1;
for (i = 0, j = 0; j < siglength && i < PROBE_LENGTH+siglength-1; ++i) {
data = inb(DEPCA_PROM);
if (dev.Sig[j] == data) { /* track signature */
++j;
} else {
if (data == dev.Sig[0]) { /* rare case... */
j = 1;
} else {
j = 0;
}
}
}
return (j == siglength);
}
/**************************************************************************
PROBE - Look for an adapter, this routine's visible to the outside
***************************************************************************/
struct nic *depca_probe(struct nic *nic, unsigned short *probe_addrs)
{
static unsigned short base[] = { 0x200, 0x300, 0 };
int i;
printf("DEPCA driver not fully functional, only probe working...\n");
if (probe_addrs == 0 || probe_addrs[0] == 0)
probe_addrs = base; /* Use defaults */
for (i = 0; (ioaddr = base[i]) != 0; ++i) {
if (DevicePresent()) {
break;
}
}
if (ioaddr != 0) {
depca_reset(nic);
/* point to NIC specific routines */
nic->reset = depca_reset;
nic->poll = depca_poll;
nic->transmit = depca_transmit;
nic->disable = depca_disable;
return nic;
}
return 0;
}

View file

@ -1,4 +1,4 @@
/*
/*
* eepro100.c -- This file implements the eepro100 driver for etherboot.
*
*
@ -8,9 +8,9 @@
*
* 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.
* quote.
*
*
* This program is free software; you can redistribute it and/or
@ -36,28 +36,28 @@
* 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.
*
* This is the etherboot 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.
* 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.
* Probing:
*
*
* Initialization:
* Using the pci.c functions of the Etherboot code, the 82557 chip is detected.
* It is verified that the BIOS initialized everything properly and if
* something is missing it is done now.
*
*
* Initialization:
*
*
* The chip is then initialized to "know" its ethernet address, and to
@ -74,12 +74,12 @@
* Transmitting and recieving.
*
* We have only one transmit descriptor. It has two buffer descriptors:
* one for the header, and the other for the data.
* 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.
*
* if there is, the buffer is copied, and the reciever is restarted.
*
* Caveats:
*
* The etherboot framework moves the code to the 32k segment from
@ -88,12 +88,8 @@
* 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)
* */
* so that you need even more headroom.
*/
/* The etherboot authors seem to dislike the argument ordering in
@ -104,6 +100,7 @@
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#include "cards.h"
#undef virt_to_bus
#define virt_to_bus(x) ((unsigned long)x)
@ -128,7 +125,7 @@ enum speedo_offsets {
};
static int read_eeprom(int ioaddr, int location);
static int read_eeprom(int location);
static void udelay (int val);
void hd (void *where, int n);
@ -183,13 +180,13 @@ enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
/* Commands that can be put in a command list entry. */
enum commands {
CmdNOp = 0,
CmdIASetup = 1,
CmdConfigure = 2,
CmdNOp = 0,
CmdIASetup = 1,
CmdConfigure = 2,
CmdMulticastList = 3,
CmdTx = 4,
CmdTDR = 5,
CmdDump = 6,
CmdTx = 4,
CmdTDR = 5,
CmdDump = 6,
CmdDiagnose = 7,
/* And some extra flags: */
@ -210,7 +207,7 @@ static inline void wait_for_cmd_done(int cmd_ioaddr)
/* Elements of the dump_statistics block. This block must be lword aligned. */
struct speedo_stats {
static struct speedo_stats {
u32 tx_good_frames;
u32 tx_coll16_errs;
u32 tx_late_colls;
@ -232,7 +229,7 @@ struct speedo_stats {
/* A speedo3 TX buffer descriptor with two buffers... */
struct TxFD {
static struct TxFD {
volatile s16 status;
s16 command;
u32 link; /* void * */
@ -243,11 +240,9 @@ struct TxFD {
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;
} txfd;
/* The Speedo3 Rx buffer descriptors. */
struct RxFD { /* Receive frame descriptor. */
volatile s16 status;
s16 command;
@ -256,7 +251,15 @@ struct RxFD { /* Receive frame descriptor. */
u16 count;
u16 size;
char packet[1518];
} rxfd;
};
#ifndef USE_INTERNAL_BUFFER
#define rxfd ((struct RxFD *)(0x10000 - sizeof(struct RxFD)))
#define ACCESS(x) x->
#else
static struct RxFD rxfd;
#define ACCESS(x) x.
#endif
@ -270,14 +273,14 @@ 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 {
static struct ConfCmd {
s16 status;
s16 command;
u32 link;
unsigned char data[22];
} confcmd = {
0, CmdConfigure,
(u32) & txfd,
(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 */
@ -288,19 +291,8 @@ struct ConfCmd {
#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 */
@ -309,12 +301,12 @@ static void calibrate_delay (void);
/* Support function: mdio_write
*
* This probably writes to the "physical media interface chip".
* This probably writes to the "physical media interface chip".
* -- REW
*/
static int mdio_write(int ioaddr, int phy_id, int location, int value)
static int mdio_write(int phy_id, int location, int value)
{
int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
@ -334,10 +326,10 @@ static int mdio_write(int ioaddr, int phy_id, int location, int value)
/* Support function: mdio_read
*
* This probably reads a register in the "physical media interface chip".
* This probably reads a register in the "physical media interface chip".
* -- REW
*/
static int mdio_read(int ioaddr, int phy_id, int location)
static int mdio_read(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);
@ -355,20 +347,19 @@ static int mdio_read(int ioaddr, int phy_id, int location)
/* 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.
* Arguments: 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)
static int read_eeprom(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;
@ -380,7 +371,7 @@ static int read_eeprom(int ioaddr, int location)
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);
@ -395,9 +386,9 @@ static int read_eeprom(int ioaddr, int location)
}
static void inline whereami (char *str)
static inline void whereami (const char *str)
{
#if 0
#if 0
printf ("%s\n", str);
sleep (2);
#endif
@ -412,9 +403,9 @@ static void inline whereami (char *str)
/* function: eepro100_reset / eth_reset
* resets the card. This is used to allow Linux to probe the card again
* from a "virginal" state....
* from a "virginal" state....
* Arguments: none
*
*
* returns: void.
*/
@ -425,7 +416,7 @@ static void eepro100_reset(struct nic *nic)
/* function: eepro100_transmit / eth_transmit
/* function: eepro100_transmit
* This transmits a packet.
*
* Arguments: char d[6]: destination ethernet address.
@ -435,7 +426,7 @@ static void eepro100_reset(struct nic *nic)
* returns: void.
*/
static void eepro100_transmit(struct nic *nic, char *d, unsigned int t, unsigned int s, char *p)
static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
{
struct eth_hdr {
unsigned char dst_addr[6];
@ -445,13 +436,13 @@ static void eepro100_transmit(struct nic *nic, char *d, unsigned int t, unsigned
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\n",
#ifdef DEBUG
printf ("transmitting type %x packet (%d bytes). status = %x, cmd=%x\n",
t, s, status, inw (ioaddr + SCBCmd));
#endif
@ -473,7 +464,7 @@ static void eepro100_transmit(struct nic *nic, char *d, unsigned int t, unsigned
txfd.tx_buf_addr1 = virt_to_bus (p);
txfd.tx_buf_size1 = s;
#ifdef DEBUG
#ifdef DEBUG
printf ("txfd: \n");
hd (&txfd, sizeof (txfd));
#endif
@ -488,7 +479,7 @@ static void eepro100_transmit(struct nic *nic, char *d, unsigned int t, unsigned
/* Wait */;
s2 = inw (ioaddr + SCBStatus);
#ifdef DEBUG
#ifdef DEBUG
printf ("Tx: Loop executed %d times.\n", TIME_OUT-to);
printf ("s1 = %x, s2 = %x.\n", s1, s2);
#endif
@ -496,11 +487,11 @@ static void eepro100_transmit(struct nic *nic, char *d, unsigned int t, unsigned
/* function: eepro100_poll / eth_poll
* This recieves a packet from the network.
* This recieves a packet from the network.
*
* Arguments: none
*
* returns: 1 if a packet was recieved.
*
* returns: 1 if a packet was recieved.
* 0 if no pacet was recieved.
* side effects:
* returns the packet in the array nic->packet.
@ -512,23 +503,23 @@ static int eepro100_poll(struct nic *nic)
int to;
to = TIME_OUT;
while (!rxfd.status && --to)
while (!ACCESS(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);
ACCESS(rxfd)status = 0;
ACCESS(rxfd)command = 0xc000;
outl(virt_to_bus(&(ACCESS(rxfd)status)), 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.\n", rxfd.count & 0x3fff);
#ifdef DEBUG
printf ("Got a packet: Len = %d.\n", ACCESS(rxfd)count & 0x3fff);
#endif
nic->packetlen = rxfd.count & 0x3fff;
memcpy (nic->packet, rxfd.packet, sizeof (rxfd.packet));
#ifdef DEBUG
nic->packetlen = ACCESS(rxfd)count & 0x3fff;
memcpy (nic->packet, ACCESS(rxfd)packet, nic->packetlen);
#ifdef DEBUG
hd (nic->packet, 0x30);
#endif
return 1;
@ -542,15 +533,14 @@ static void eepro100_disable(struct nic *nic)
/* exported function: eepro100_probe / eth_probe
* initializes a card
*
* side effects:
*
* 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, struct pci_device *p)
{
int pci_index;
u16 sum = 0;
int i, j, to;
unsigned short value;
@ -569,19 +559,19 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
/* Ok. Got one. Read the eeprom. */
for (j = 0, i = 0; i < 0x40; i++) {
value = read_eeprom(ioaddr, i);
value = read_eeprom(i);
eeprom[i] = value;
sum += value;
}
/* From Matt Hortman <mbhortman@acpthinclient.com> */
if (p->dev_id == PCI_DEVICE_ID_INTEL_82557 ){
if (p->dev_id == PCI_DEVICE_ID_INTEL_82557 ){
/*
* check to make sure the bios properly set the
* 82557 (or 82558) to be bus master
*
* from eepro100.c in 2.2.9 kernel source
*/
* from eepro100.c in 2.2.9 kernel source
*/
pcibios_read_config_word(pci_bus, p->devfn, PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
@ -597,12 +587,12 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
printf("\nPCI latency timer (CFLT) is unreasonably low at %d. Setting to 32 clocks.\n", pci_latency);
pcibios_write_config_byte(pci_bus, p->devfn, PCI_LATENCY_TIMER, 32);
}
}
}
printf ("Ethernet addr: ");
for (i=0;i<6;i++) {
nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
printf ("%b%c", nic->node_addr[i] , i < 5?':':' ');
printf ("%b%c", nic->node_addr[i] , i < 5?':':' ');
}
printf ("\n");
@ -617,37 +607,37 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
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);
ACCESS(rxfd)status = 0x0001;
ACCESS(rxfd)command = 0x0000;
ACCESS(rxfd)link = virt_to_bus(&(ACCESS(rxfd)status));
ACCESS(rxfd)rx_buf_addr = (int) &nic->packet;
ACCESS(rxfd)count = 0;
ACCESS(rxfd)size = 1528;
outl(virt_to_bus(&(ACCESS(rxfd)status)), 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);
ACCESS(rxfd)status = 0;
ACCESS(rxfd)command = 0xc000;
outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);
outw(INT_MASK | RX_START, ioaddr + SCBCmd);
/* INIT TX stuff. */
/* Base = 0 */
@ -660,15 +650,15 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
txfd.command = (CmdIASetup);
txfd.status = 0x0000;
txfd.link = virt_to_bus (&confcmd);
{
char *p = (char *)&txfd.tx_desc_addr;
{
char *t = (char *)&txfd.tx_desc_addr;
for (i=0;i<6;i++)
p[i] = nic->node_addr[i];
t[i] = nic->node_addr[i];
}
#ifdef DEBUG
#ifdef DEBUG
printf ("Setup_eaddr:\n");
hd (&txfd, 0x20);
#endif
@ -676,20 +666,20 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
options = 0x00; /* Autosense */
promisc = 0;
printf ("eeprom[6] = %x \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;
int mdi_reg23 = mdio_read(eeprom[6] & 0x1f, 23) | 0x0422;
if (congenb)
mdi_reg23 |= 0x0100;
printf(" DP83840 specific setup, setting register 23 to %x.\n",
mdi_reg23);
mdio_write(ioaddr, eeprom[6] & 0x1f, 23, mdi_reg23);
mdio_write(eeprom[6] & 0x1f, 23, mdi_reg23);
}
whereami ("Done DP8340 special setup.");
if (options != 0) {
mdio_write(ioaddr, eeprom[6] & 0x1f, 0,
mdio_write(eeprom[6] & 0x1f, 0,
((options & 0x20) ? 0x2000 : 0) | /* 100mbps? */
((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */
whereami ("set mdio_register.");
@ -715,7 +705,7 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
while (!txfd.status && --to)
/* Wait */;
#ifdef DEBUG
#ifdef DEBUG
printf ("\nLoop executed %d times.\n", TIME_OUT-to);
#endif
nic->reset = eepro100_reset;
@ -725,8 +715,7 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
return nic;
}
static int loops_per_sec;
static int loops_per_usec;
static int loops_per_usec = 300; /* totally bogus value */
static void udelay (int val)
{
@ -737,79 +726,9 @@ static void udelay (int val)
}
}
#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
#ifdef DEBUG
/* Hexdump a number of bytes from memory... */
void hd (void *where, int n)

View file

@ -1,10 +1,10 @@
/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for EtherBoot 4.0 */
/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Etherboot */
#define LINUX_OUT_MACROS
#include "etherboot.h"
#include "nic.h"
/*#include <linux/pci.h>*/
#include "cards.h"
#include "epic100.h"
#undef virt_to_bus
@ -23,7 +23,7 @@
#define DEBUG_EEPROM
*/
static int epic_debug = 0; /* debug level */
#define EPIC_DEBUG 0 /* debug level */
/* The EPIC100 Rx and Tx buffer descriptors. */
struct epic_rx_desc {
@ -50,12 +50,12 @@ struct epic_tx_desc {
#define delay(nanosec) do { int _i = 3; while (--_i > 0) \
{ __SLOW_DOWN_IO; }} while (0)
static void epic100_open();
static void epic100_init_ring();
static void epic100_open(void);
static void epic100_init_ring(void);
static void epic100_disable(struct nic *nic);
static int epic100_poll(struct nic *nic);
static void epic100_transmit(struct nic *nic, char *destaddr,
unsigned int type, unsigned int len, char *data);
static int epic100_poll(struct nic *nic);
static void epic100_transmit(struct nic *nic, const char *destaddr,
unsigned int type, unsigned int len, const char *data);
static int read_eeprom(int location);
static int mii_read(int phy_id, int location);
@ -77,34 +77,39 @@ static int ptcdar ;
static int eththr ;
static unsigned int cur_rx, cur_tx; /* The next free ring entry */
#ifdef DEBUG_EEPROM
#ifdef DEBUG_EEPROM
static unsigned short eeprom[64];
#endif
signed char phys[4]; /* MII device addresses. */
struct epic_rx_desc rx_ring[RX_RING_SIZE];
struct epic_tx_desc tx_ring[TX_RING_SIZE];
static char rx_packet[PKT_BUF_SZ * RX_RING_SIZE];
static char tx_packet[PKT_BUF_SZ * TX_RING_SIZE];
static signed char phys[4]; /* MII device addresses. */
static struct epic_rx_desc rx_ring[RX_RING_SIZE];
static struct epic_tx_desc tx_ring[TX_RING_SIZE];
#ifndef USE_INTERNAL_BUFFER
#define rx_packet ((char *)0x10000 - PKT_BUF_SZ * RX_RING_SIZE)
#define tx_packet ((char *)0x10000 - PKT_BUF_SZ * RX_RING_SIZE - PKT_BUF_SZ * TX_RING_SIZE)
#else
static char rx_packet[PKT_BUF_SZ * RX_RING_SIZE];
static char tx_packet[PKT_BUF_SZ * TX_RING_SIZE];
#endif
/***********************************************************************/
/* Externally visible functions */
/***********************************************************************/
static void
static void
epic100_reset(struct nic *nic)
{
/* Soft reset the chip. */
outl(GC_SOFT_RESET, genctl);
}
struct nic*
struct nic*
epic100_probe(struct nic *nic, unsigned short *probeaddrs)
{
unsigned short sum = 0;
unsigned short value;
int i, j;
int i;
unsigned short* ap;
int phy, phy_idx;
unsigned int phy, phy_idx;
if (probeaddrs == 0 || probeaddrs[0] == 0)
return 0;
@ -131,23 +136,23 @@ epic100_probe(struct nic *nic, unsigned short *probeaddrs)
prcdar = ioaddr + PRCDAR; /* PCI Receive Current Descr Address */
ptcdar = ioaddr + PTCDAR; /* PCI Transmit Current Descr Address */
eththr = ioaddr + ETHTHR; /* Early Transmit Threshold */
/* Reset the chip & bring it out of low-power mode. */
outl(GC_SOFT_RESET, genctl);
/* Disable ALL interrupts by setting the interrupt mask. */
outl(INTR_DISABLE, intmask);
/*
/*
* set the internal clocks:
* Application Note 7.15 says:
* In order to set the CLOCK TEST bit in the TEST register,
* In order to set the CLOCK TEST bit in the TEST register,
* perform the following:
*
* Write 0x0008 to the test register at least sixteen
* Write 0x0008 to the test register at least sixteen
* consecutive times.
*
* The CLOCK TEST bit is Write-Only. Writing it several times
* The CLOCK TEST bit is Write-Only. Writing it several times
* consecutively insures a successful write to the bit...
*/
@ -155,46 +160,46 @@ epic100_probe(struct nic *nic, unsigned short *probeaddrs)
outl(0x00000008, test);
}
#ifdef DEBUG_EEPROM
#ifdef DEBUG_EEPROM
for (i = 0; i < 64; i++) {
value = read_eeprom(i);
eeprom[i] = value;
sum += value;
}
if (epic_debug > 1) {
printf("EEPROM contents\n");
for (i = 0; i < 64; i++) {
printf(" %02x%s", eeprom[i], i % 16 == 15 ? "\n" : "");
}
#if (EPIC_DEBUG > 1)
printf("EEPROM contents\n");
for (i = 0; i < 64; i++) {
printf(" %02x%s", eeprom[i], i % 16 == 15 ? "\n" : "");
}
#endif
#endif
/* This could also be read from the EEPROM. */
ap = (unsigned short*)nic->node_addr;
for (i = 0; i < 3; i++)
*ap++ = inw(lan0 + i*4);
printf(" I/O %x ", ioaddr);
for (i = 0; i < 6; i++)
printf ("%b%c", nic->node_addr[i] , i < 5 ?':':' ');
printf ("%b%c", nic->node_addr[i] , i < 5 ?':':' ');
/* Find the connected MII xcvrs. */
for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(phys); phy++) {
int mii_status = mii_read(phy, 0);
if (mii_status != 0xffff && mii_status != 0x0000) {
phys[phy_idx++] = phy;
if (epic_debug > 1) {
printf("MII transceiver found at address %d.\n", phy);
}
#if (EPIC_DEBUG > 1)
printf("MII transceiver found at address %d.\n", phy);
#endif
}
}
if (phy_idx == 0) {
if (epic_debug > 1) {
printf("***WARNING***: No MII transceiver found!\n");
}
#if (EPIC_DEBUG > 1)
printf("***WARNING***: No MII transceiver found!\n");
#endif
/* Use the known PHY address of the EPII. */
phys[0] = 3;
}
@ -212,7 +217,6 @@ epic100_probe(struct nic *nic, unsigned short *probeaddrs)
static void
epic100_open()
{
int i;
int mii_reg5;
int full_duplex = 0;
unsigned long tmp;
@ -240,8 +244,8 @@ epic100_open()
outl(virt_to_bus(&rx_ring), prcdar);
outl(virt_to_bus(&tx_ring), ptcdar);
/* Start the chip's Rx process: Don't receive broadcast */
outl(0, rxcon);
/* Start the chip's Rx process: receive unicast and broadcast */
outl(0x04, rxcon);
outl(CR_START_RX | CR_QUEUE_RX, command);
putchar('\n');
@ -267,7 +271,7 @@ epic100_init_ring()
/* Mark the last entry as wrapping the ring. */
rx_ring[i-1].next = virt_to_bus(&rx_ring[0]);
/*
/*
*The Tx buffer descriptor is filled in as needed,
* but we do need to clear the ownership bit.
*/
@ -282,7 +286,7 @@ epic100_init_ring()
tx_ring[i-1].next = virt_to_bus(&tx_ring[0]);
}
/* function: epic100_transmit / eth_transmit
/* function: epic100_transmit
* This transmits a packet.
*
* Arguments: char d[6]: destination ethernet address.
@ -291,9 +295,9 @@ epic100_init_ring()
* char *p: the data for the packet.
* returns: void.
*/
static void
epic100_transmit(struct nic *nic, char *destaddr, unsigned int type,
unsigned int len, char *data)
static void
epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
unsigned int len, const char *data)
{
unsigned short nstype;
unsigned short status;
@ -322,9 +326,9 @@ epic100_transmit(struct nic *nic, char *destaddr, unsigned int type,
len += ETHER_HDR_SIZE;
/*
* Caution: the write order is important here,
* set the base address with the "ownership"
/*
* Caution: the write order is important here,
* set the base address with the "ownership"
* bits last.
*/
tx_ring[entry].txlength = (len >= 60 ? len : 60);
@ -344,32 +348,32 @@ epic100_transmit(struct nic *nic, char *destaddr, unsigned int type,
}
if ((status & TRING_OWN) == 0) {
#ifdef DEBUG_TX
printf("tx done after %d loop(s), status %x\n",
#ifdef DEBUG_TX
printf("tx done after %d loop(s), status %x\n",
TIME_OUT-to, tx_ring[entry].status );
#endif
return;
}
if (to == 0) {
printf("OOPS, Something wrong with transmitter. status=%x\n",
printf("OOPS, Something wrong with transmitter. status=%x\n",
tx_ring[entry].status);
}
}
/* function: epic100_poll / eth_poll
* This receives a packet from the network.
* This receives a packet from the network.
*
* Arguments: none
*
* returns: 1 if a packet was received.
*
* returns: 1 if a packet was received.
* 0 if no pacet was received.
* side effects:
* returns the packet in the array nic->packet.
* returns the length of the packet in nic->packetlen.
*/
static int
static int
epic100_poll(struct nic *nic)
{
int to;
@ -380,14 +384,14 @@ epic100_poll(struct nic *nic)
entry = cur_rx % RX_RING_SIZE;
cur_rx++;
to = TIME_OUT;
status = rx_ring[entry].status;
while ( (status & RRING_OWN) == RRING_OWN && --to) {
status = rx_ring[entry].status;
}
if (to == 0) {
#ifdef DEBUG_RX
#ifdef DEBUG_RX
printf("epic_poll: time out! status %x\n", status);
#endif
/* Restart Receiver */
@ -397,8 +401,9 @@ epic100_poll(struct nic *nic)
/* We own the next entry, it's a new packet. Send it up. */
if (epic_debug > 4)
printf("epic_poll: entry %d status %8x\n", entry, status);
#if (EPIC_DEBUG > 4)
printf("epic_poll: entry %d status %8x\n", entry, status);
#endif
if (status & 0x2000) {
printf("epic_poll: Giant packet\n");
@ -427,13 +432,13 @@ epic100_poll(struct nic *nic)
}
static void
static void
epic100_disable(struct nic *nic)
{
}
#ifdef DEBUG_EEPROM
#ifdef DEBUG_EEPROM
/* Serial EEPROM section. */
/* EEPROM_Ctrl bits. */
@ -452,16 +457,16 @@ epic100_disable(struct nic *nic)
#define eeprom_delay(n) delay(n)
static int
static int
read_eeprom(int location)
{
int i;
int retval = 0;
int read_cmd = location | EE_READ_CMD;
outl(EE_ENB & ~EE_CS, eectl);
outl(EE_ENB, eectl);
/* Shift the read command bits out. */
for (i = 10; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
@ -473,7 +478,7 @@ read_eeprom(int location)
eeprom_delay(250);
}
outl(EE_ENB, eectl);
for (i = 16; i > 0; i--) {
outl(EE_ENB | EE_SHIFT_CLK, eectl);
eeprom_delay(100);
@ -492,7 +497,7 @@ read_eeprom(int location)
#define MII_READOP 1
#define MII_WRITEOP 2
static int
static int
mii_read(int phy_id, int location)
{
int i;

View file

@ -1,11 +1,11 @@
#ifndef _EPIC100_H_
#ifndef _EPIC100_H_
# define _EPIC100_H_
#ifndef PCI_VENDOR_SMC
#ifndef PCI_VENDOR_SMC
# define PCI_VENDOR_SMC 0x10B8
#endif
#ifndef PCI_DEVICE_SMC_EPIC100
#ifndef PCI_DEVICE_SMC_EPIC100
# define PCI_DEVICE_SMC_EPIC100 0x0005
#endif
@ -16,24 +16,24 @@ enum epic100_registers {
COMMAND= 0, /* Control Register */
INTSTAT= 4, /* Interrupt Status */
INTMASK= 8, /* Interrupt Mask */
GENCTL = 0x0C, /* General Control */
GENCTL = 0x0C, /* General Control */
NVCTL = 0x10, /* Non Volatile Control */
EECTL = 0x14, /* EEPROM Control */
TEST = 0x1C, /* Test register: marked as reserved (see in source code) */
TEST = 0x1C, /* Test register: marked as reserved (see in source code) */
CRCCNT = 0x20, /* CRC Error Counter */
ALICNT = 0x24, /* Frame Alignment Error Counter */
ALICNT = 0x24, /* Frame Alignment Error Counter */
MPCNT = 0x28, /* Missed Packet Counter */
MMCTL = 0x30, /* MII Management Interface Control */
MMDATA = 0x34, /* MII Management Interface Data */
MMDATA = 0x34, /* MII Management Interface Data */
MIICFG = 0x38, /* MII Configuration */
IPG = 0x3C, /* InterPacket Gap */
LAN0 = 0x40, /* MAC address. (0x40-0x48) */
IDCHK = 0x4C, /* BoardID/ Checksum */
MC0 = 0x50, /* Multicast filter table. (0x50-0x5c) */
RXCON = 0x60, /* Receive Control */
TXCON = 0x70, /* Transmit Control */
RXCON = 0x60, /* Receive Control */
TXCON = 0x70, /* Transmit Control */
TXSTAT = 0x74, /* Transmit Status */
PRCDAR = 0x84, /* PCI Receive Current Descriptor Address */
PRCDAR = 0x84, /* PCI Receive Current Descriptor Address */
PRSTAT = 0xA4, /* PCI Receive DMA Status */
PRCPTHR= 0xB0, /* PCI Receive Copy Threshold */
PTCDAR = 0xC4, /* PCI Transmit Current Descriptor Address */
@ -52,7 +52,7 @@ enum epic100_registers {
/* Interrupt register bits. NI means No Interrupt generated */
#define INTR_RX_THR_STA (0x00400000) /* rx copy threshold status NI */
#define INTR_RX_THR_STA (0x00400000) /* rx copy threshold status NI */
#define INTR_RX_BUFF_EMPTY (0x00200000) /* rx buffers empty. NI */
#define INTR_TX_IN_PROG (0x00100000) /* tx copy in progess. NI */
#define INTR_RX_IN_PROG (0x00080000) /* rx copy in progress. NI */
@ -93,8 +93,8 @@ enum epic100_registers {
#define GC_RX_PREEMPT_TX (0x00000040)
#define GC_TX_PREEMPT_RX (0x00000080)
/*
* Receive FIFO Threshold values
/*
* Receive FIFO Threshold values
* Control the level at which the PCI burst state machine
* begins to empty the receive FIFO. Possible values: 0-3
*
@ -143,7 +143,7 @@ enum epic100_registers {
#define TX_SLOT_TIME (0x00000078)
/* Bytes transferred to chip before transmission starts. */
#define TX_FIFO_THRESH 128 /* Rounded down to 4 byte units. */
#define TX_FIFO_THRESH 128 /* Rounded down to 4 byte units. */
/* description of rx descriptors status bits */
#define RRING_PKT_INTACT (0x0001)
@ -170,7 +170,7 @@ enum epic100_registers {
#define TRING_HB_COLL (0x0020) /* Collision detect Heartbeat */
#define TRING_WIN_COLL (0x0040) /* out of window collision */
#define TRING_DEFERRED (0x0080) /* Deferring */
#define TRING_COLL_COUNT (0x0F00) /* collision counter (mask) */
#define TRING_COLL_COUNT (0x0F00) /* collision counter (mask) */
#define TRING_COLL_EXCESS (0x1000) /* tx aborted: excessive colls */
#define TRING_OWN (0x8000) /* desc ownership bit */
@ -185,4 +185,4 @@ enum epic100_registers {
#define TD_NOCRC (0x0008) /* No CRC generated */
#define TD_LASTDESC (0x0010) /* Last desc for this frame */
#endif /* _EPIC100_H_ */
#endif /* _EPIC100_H_ */

View file

@ -6,13 +6,31 @@ Author: Martin Renters
**************************************************************************/
/* Enable GRUB-specific stuff. */
#define GRUB 1
#ifdef GRUB
/* Include GRUB-specific macros and prototypes here. */
#include <shared.h>
# include <shared.h>
/* FIXME: For now, enable the DHCP support. Perhaps I should segregate
the DHCP support from the BOOTP support, and permit both to
co-exist. */
#undef NO_DHCP_SUPPORT
# undef NO_DHCP_SUPPORT
/* In GRUB, the relocated address in Etherboot doesn't have any sense.
Just define it as a bogus value. */
# define RELOC 0
/* Force to use the internal buffer. */
# define INTERNAL_BOOTP_DATA 1
/* Likewise. */
# define USE_INTERNAL_BUFFER 1
/* FIXME: Should be an option. */
# define BACKOFF_LIMIT 7
#endif /* GRUB */
#include "osdep.h"
@ -29,37 +47,74 @@ Author: Martin Renters
#define TAGGED_IMAGE /* choose at least one */
#endif
#if 0
# define ESC 0x1B
#else
#ifdef GRUB
# define CTRL_C 3
#endif
#else /* ! GRUB */
# define ESC 0x1B
#endif /* ! GRUB */
#ifndef DEFAULT_BOOTFILE
#ifndef DEFAULT_BOOTFILE
#define DEFAULT_BOOTFILE "/tftpboot/kernel"
#endif
#ifndef MAX_TFTP_RETRIES
/* Clean up console settings... mainly CONSOLE_CRT and CONSOLE_SERIAL are used
* in the sources (except start.S and serial.S which cannot include
* etherboot.h). At least one of the CONSOLE_xxx has to be set, and
* CONSOLE_DUAL sets both CONSOLE_CRT and CONSOLE_SERIAL. If none is set,
* CONSOLE_CRT is assumed. */
#ifdef CONSOLE_DUAL
#undef CONSOLE_CRT
#define CONSOLE_CRT
#undef CONSOLE_SERIAL
#define CONSOLE_SERIAL
#endif
#if defined(CONSOLE_CRT) && defined(CONSOLE_SERIAL)
#undef CONSOLE_DUAL
#define CONSOLE_DUAL
#endif
#if !defined(CONSOLE_CRT) && !defined(CONSOLE_SERIAL)
#define CONSOLE_CRT
#endif
#ifndef DOWNLOAD_PROTO_NFS
#undef DOWNLOAD_PROTO_TFTP
#define DOWNLOAD_PROTO_TFTP /* default booting protocol */
#endif
#ifdef DOWNLOAD_PROTO_TFTP
#define download(fname,loader) tftp((fname),(loader))
#endif
#ifdef DOWNLOAD_PROTO_NFS
#define download(fname,loader) nfs((fname),(loader))
#endif
#ifndef MAX_TFTP_RETRIES
#define MAX_TFTP_RETRIES 20
#endif
#ifndef MAX_BOOTP_RETRIES
#ifndef MAX_BOOTP_RETRIES
#define MAX_BOOTP_RETRIES 20
#endif
#ifndef MAX_BOOTP_EXTLEN
#if defined(INTERNAL_BOOTP_DATA) || (RELOC >= 0x94200)
#ifndef MAX_BOOTP_EXTLEN
#if (RELOC < 0x94000)
/* Force internal buffer (if external buffer would overlap with our code...) */
#undef INTERNAL_BOOTP_DATA
#define INTERNAL_BOOTP_DATA
#endif
/* sizeof(struct bootp_t) == 0x240 */
#if defined(INTERNAL_BOOTP_DATA) || (RELOC >= 0x94240)
#define MAX_BOOTP_EXTLEN 1024
#else
#define MAX_BOOTP_EXTLEN (1024-sizeof(struct bootp_t))
#endif /* INTERNAL_BOOTP_DATA || RELOC > 0x94200 */
#endif
#endif
#ifndef MAX_ARP_RETRIES
#ifndef MAX_ARP_RETRIES
#define MAX_ARP_RETRIES 20
#endif
#ifndef MAX_RPC_RETRIES
#ifndef MAX_RPC_RETRIES
#define MAX_RPC_RETRIES 20
#endif
@ -74,7 +129,7 @@ Author: Martin Renters
/* packet retransmission timeout in ticks */
#define TFTP_REXMT (3*TICKS_PER_SEC)
#ifndef NULL
#ifndef NULL
#define NULL ((void *)0)
#endif
@ -113,7 +168,8 @@ Author: Martin Renters
#define BOOTP_SERVER 67
#define BOOTP_CLIENT 68
#define TFTP 69
#define TFTP_PORT 69
#define SUNRPC_PORT 111
#define IP_UDP 17
/* Same after going through htonl */
@ -195,7 +251,9 @@ Author: Martin Renters
#define RFC1533_VENDOR_MAGIC 128
#define RFC1533_VENDOR_ADDPARM 129
#define RFC1533_VENDOR_HOWTO 132 /* used by FreeBSD */
#ifdef IMAGE_FREEBSD
#define RFC1533_VENDOR_HOWTO 132
#endif
#define RFC1533_VENDOR_MNUOPTS 160
#define RFC1533_VENDOR_SELECTION 176
#define RFC1533_VENDOR_MOTD 184
@ -228,7 +286,9 @@ Author: Martin Renters
#define AWAIT_ARP 0
#define AWAIT_BOOTP 1
#define AWAIT_TFTP 2
#define AWAIT_RARP 3
#define AWAIT_RARP 3
#define AWAIT_RPC 4
#define AWAIT_QDRAIN 5 /* drain queue, process ARP requests */
typedef struct {
unsigned long s_addr;
@ -296,7 +356,7 @@ struct bootp_t {
char bp_vend[BOOTP_VENDOR_LEN];
#else
char bp_vend[DHCP_OPT_LEN];
#endif /* NO_DHCP_SUPPORT */
#endif /* NO_DHCP_SUPPORT */
};
struct bootpd_t {
@ -329,6 +389,60 @@ struct tftp_t {
#define TFTP_MIN_PACKET (sizeof(struct iphdr) + sizeof(struct udphdr) + 4)
struct rpc_t {
struct iphdr ip;
struct udphdr udp;
union {
char data[300]; /* longest RPC call must fit!!!! */
struct {
long id;
long type;
long rpcvers;
long prog;
long vers;
long proc;
long data[1];
} call;
struct {
long id;
long type;
long rstatus;
long verifier;
long v2;
long astatus;
long data[1];
} reply;
} u;
};
#define PROG_PORTMAP 100000
#define PROG_NFS 100003
#define PROG_MOUNT 100005
#define MSG_CALL 0
#define MSG_REPLY 1
#define PORTMAP_GETPORT 3
#define MOUNT_ADDENTRY 1
#define MOUNT_UMOUNTALL 4
#define NFS_LOOKUP 4
#define NFS_READ 6
#define NFS_FHSIZE 32
#define NFSERR_PERM 1
#define NFSERR_NOENT 2
#define NFSERR_ACCES 13
/* Block size used for NFS read accesses. A RPC reply packet (including all
* headers) must fit within a single Ethernet frame to avoid fragmentation.
* Chosen to be a power of two, as most NFS servers are optimized for this. */
#define NFS_READ_SIZE 1024
#define FLOPPY_BOOT_LOCATION 0x7c00
#define ROM_INFO_LOCATION 0x7dfa
/* at end of floppy boot block */
@ -338,30 +452,45 @@ struct rom_info {
};
/***************************************************************************
extern int rarp P((void));
External prototypes
***************************************************************************/
/* main.c */
extern void print_network_configuration (void);
#ifdef GRUB
extern void print_network_configuration P((void));
#endif /* GRUB */
#if 0
#ifndef GRUB
extern void print_bytes P((unsigned char *bytes, int len));
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 tftpkernel P((unsigned char *, int, int, int));
extern int downloadkernel P((unsigned char *, int, int, int));
extern int tftp P((char *name, int (*)(unsigned char *, int, int, int)));
#endif
extern void rpc_init(void);
extern int nfs P((const char *name, int (*)(unsigned char *, int, int, int)));
extern void nfs_umountall P((int));
#endif /* ! GRUB */
extern int bootp P((void));
extern int rarp 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, int timeout));
unsigned int destsock, int len, const void *buf));
extern int await_reply P((int type, int ival, void *ptr, int timeout));
extern int decode_rfc1533 P((unsigned char *, int, int, int));
extern unsigned short ipchksum P((unsigned short *, int len));
extern void rfc951_sleep P((int));
extern void cleanup_net P((void));
extern void cleanup P((void));
#if 0
/* config.c */
extern void print_config(void);
extern void eth_reset(void);
extern int eth_probe(void);
extern int eth_poll(void);
extern void eth_transmit(const char *d, unsigned int t, unsigned int s, const void *p);
extern void eth_disable(void);
#ifndef GRUB
/* bootmenu.c */
extern int execute P((char *string));
extern void bootmenu P((int));
@ -374,49 +503,53 @@ extern void selectImage P((char **));
#if defined(AOUT_IMAGE) || defined(ELF_IMAGE)
extern int howto;
#endif
extern int os_tftp P((unsigned int block,unsigned char *data,int len));
#endif
extern int os_download P((unsigned int, unsigned char *,unsigned int));
#endif /* ! GRUB */
/* misc.c */
extern void twiddle P((void));
extern void sleep P((int secs));
#if 0
#ifndef GRUB
extern int strcasecmp P((char *a, char *b));
extern char *substr P((char *a, char *b));
#endif
#endif /* ! GRUB */
extern int getdec P((char **));
#if 0
extern void printf(); /* old style to avoid varargs */
extern char *sprintf();
extern int inet_ntoa P((char *p, in_addr *i));
extern void gateA20 P((void));
#ifndef GRUB
extern void printf P((const char *, ...));
extern char *sprintf P((char *, const char *, ...));
extern int inet_aton P((char *p, in_addr *i));
extern void gateA20_set P((void));
extern void gateA20_unset P((void));
extern void putchar P((int));
extern int getchar ();
extern int iskey P((void));
extern int getchar P((void));
extern int iskey P((void));
/* start*.S */
extern int getc P((void));
extern void putc P((int));
extern void putc P((int));
extern int ischar P((void));
extern int getshift P((void));
extern unsigned short memsize P((void));
extern unsigned int memsize P((void));
extern unsigned short basememsize P((void));
extern void disk_init P((void));
extern unsigned int disk_read P((int drv,int c,int h,int s,char *buf));
extern void xstart P((unsigned long, unsigned long, char *));
extern long currticks P((void));
extern unsigned long currticks P((void));
extern int setjmp P((void *jmpbuf));
extern void longjmp P((void *jmpbuf, int where));
extern void exit P((int status));
extern void slowdownio P((void));
/* serial.S */
extern int serial_getc P((void));
extern void serial_putc P((int));
extern int serial_ischar P((void));
extern void serial_init P((void));
extern int serial_init P((void));
/* ansiesc.c */
extern void ansi_reset P((void));
extern void enable_cursor P((int));
extern void handleansi P((unsigned char));
/* md5.c */
extern void md5_put P((unsigned int ch));
@ -424,53 +557,58 @@ extern void md5_done P((unsigned char *buf));
/* floppy.c */
extern int bootdisk P((int dev,int part));
#endif
#endif /* ! GRUB */
/***************************************************************************
External variables
***************************************************************************/
/* main.c */
#ifdef GRUB
extern int ip_abort;
extern int network_ready;
#if 0
extern char *kernel;
extern char kernel_buf[];
#endif
#endif /* GRUB */
#ifndef GRUB
extern const char *kernel;
extern char kernel_buf[128];
#endif /* ! GRUB */
extern struct rom_info rom;
#if 0
#ifndef GRUB
extern int hostnamelen;
extern unsigned long netmask;
extern int jmp_bootmenu[10];
extern char kernel_buf[128];
#endif
extern int jmp_bootmenu[10];
#endif /* ! GRUB */
extern struct arptable_t arptable[MAX_ARP];
#if 0
extern char *imagelist[RFC1533_VENDOR_NUMOFIMG];
extern char *motd[RFC1533_VENDOR_NUMOFMOTD];
extern int menutmo,menudefault;
extern struct bootpd_t bootp_data;
#ifndef GRUB
#ifdef IMAGE_MENU
extern char *motd[RFC1533_VENDOR_NUMOFMOTD];
extern int menutmo,menudefault;
extern unsigned char *defparams;
extern int defparams_max;
#endif
#ifdef ETHERBOOT32
#define INTERNAL_BOOTP_DATA 1
#ifdef INTERNAL_BOOTP_DATA
#define BOOTP_DATA_ADDR (&bootp_data)
#else
#endif /* ! GRUB */
#if defined(ETHERBOOT32) && !defined(INTERNAL_BOOTP_DATA)
#define BOOTP_DATA_ADDR ((struct bootpd_t *)0x93C00)
#endif /* INTERNAL_BOOTP_DATA */
#endif
#ifdef ETHERBOOT16
#else
extern struct bootpd_t bootp_data;
#define BOOTP_DATA_ADDR (&bootp_data)
#endif
extern unsigned char *end_of_rfc1533;
#ifdef IMAGE_FREEBSD
extern int freebsd_howto;
#endif
/* config.c */
extern struct nic nic;
/* bootmenu.c */
/* osloader.c */
#if 0
#ifndef GRUB
/* created by linker */
extern char _edata[], _end[];
#endif
extern char _start[], _edata[], _end[];
#endif /* ! GRUB */
/*
* Local variables:

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Based on "src/main.c" in etherboot-4.4.2. */
/* Based on "src/main.c" in etherboot-4.5.8. */
/**************************************************************************
ETHERBOOT - BOOTP/TFTP Bootstrap Program
@ -32,12 +32,12 @@ Author: Martin Renters
#include <etherboot.h>
#include <nic.h>
#include <netboot_config.h>
static int retry;
static unsigned short isocket = 2000;
static unsigned short osocket;
static unsigned short iport = 2000;
static unsigned short oport;
static unsigned short block, prevblock;
static int bcounter;
static struct tftp_t tp, saved_tp;
static int packetsize;
static int buf_eof, buf_read;
@ -58,9 +58,10 @@ buf_fill (int abort)
struct tftp_t *tr;
#ifdef CONGESTED
if (! await_reply (AWAIT_TFTP, isocket, NULL, block ? TFTP_REXMT : 0))
if (! await_reply (AWAIT_TFTP, iport, NULL,
block ? TFTP_REXMT : TIMEOUT))
#else
if (! await_reply (AWAIT_TFTP, isocket, NULL, 0))
if (! await_reply (AWAIT_TFTP, iport, NULL, TIMEOUT))
#endif
{
if (ip_abort)
@ -74,7 +75,7 @@ buf_fill (int abort)
#endif
rfc951_sleep (retry);
if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
++isocket, TFTP, len, (char *) &tp))
++iport, TFTP_PORT, len, &tp))
return 0;
continue;
@ -88,8 +89,8 @@ buf_fill (int abort)
grub_printf ("<REXMT>\n");
# endif
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
isocket, osocket,
TFTP_MIN_PACKET, (char *) &tp);
iport, oport,
TFTP_MIN_PACKET, &tp);
continue;
}
#endif
@ -158,8 +159,8 @@ buf_fill (int abort)
"RFC1782 error")
+ TFTP_MIN_PACKET + 1);
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
isocket, ntohs (tr->udp.src),
len, (char *) &tp);
iport, ntohs (tr->udp.src),
len, &tp);
return 0;
}
@ -195,20 +196,20 @@ buf_fill (int abort)
/* Neither TFTP_OACK nor TFTP_DATA. */
break;
/* Block order. */
if (block && (block != prevblock + 1))
if ((block || bcounter) && (block != prevblock + 1))
/* Block order should be continuous */
tp.u.ack.block = htons (block = prevblock);
/* Should be continuous. */
tp.opcode = abort ? htons (TFTP_ERROR) : htons (TFTP_ACK);
osocket = ntohs (tr->udp.src);
oport = ntohs (tr->udp.src);
#ifdef TFTP_DEBUG
grub_printf ("ACK\n");
#endif
/* Ack. */
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, isocket,
osocket, TFTP_MIN_PACKET, (char *) &tp);
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, iport,
oport, TFTP_MIN_PACKET, &tp);
if (abort)
{
@ -217,7 +218,7 @@ buf_fill (int abort)
}
/* Retransmission or OACK. */
if (block <= prevblock)
if ((unsigned short) (block - prevblock) != 1)
/* Don't process. */
continue;
@ -225,6 +226,10 @@ buf_fill (int abort)
/* Is it the right place to zero the timer? */
retry = 0;
/* In GRUB, this variable doesn't play any important role at all,
but use it for consistency with Etherboot. */
bcounter++;
/* Copy the downloaded data to the buffer. */
grub_memmove (buf + buf_read, tr->u.data.download, len);
buf_read += len;
@ -246,18 +251,27 @@ send_rrq (void)
block = 0;
prevblock = 0;
packetsize = TFTP_DEFAULTSIZE_PACKET;
bcounter = 0;
buf = (char *) FSYS_BUF;
buf_eof = 0;
buf_read = 0;
saved_filepos = 0;
/* Clear out the Rx queue first. It contains nothing of interest,
* except possibly ARP requests from the DHCP/TFTP server. We use
* polling throughout Etherboot, so some time may have passed since we
* last polled the receive queue, which may now be filled with
* broadcast packets. This will cause the reply to the packets we are
* about to send to be lost immediately. Not very clever. */
await_reply (AWAIT_QDRAIN, 0, NULL, 0);
#ifdef TFTP_DEBUG
grub_printf ("send_rrq ()\n");
#endif
/* Send the packet. */
return udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++isocket, TFTP,
len, (char *) &tp);
return udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
TFTP_PORT, len, &tp);
}
/* Mount the network drive. If the drive is ready, return one, otherwise

View file

@ -11,10 +11,9 @@ Ken Yap, January 1998
* your option) any later version.
*/
/* to get some global routines like printf */
#include "etherboot.h"
/* to get the interface to the body of the program */
#include "nic.h"
#include "cards.h"
/* Sources of information:
@ -41,7 +40,7 @@ Ken Yap, January 1998
#define CUC_START 0x0100
#define CUC_RESUME 0x0200
#define CUC_SUSPEND 0x0300
#define CUC_SUSPEND 0x0300
#define RX_START 0x0010
#define RX_RESUME 0x0020
#define RX_SUSPEND 0x0030
@ -67,7 +66,7 @@ enum commands {
CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7};
/*
Details of the EtherLink16 Implementation
Details of the EtherLink16 Implementation
The 3c507 and NI5210 are generic shared-memory i82586 implementations.
3c507: The host can map 16K, 32K, 48K, or 64K of the 64K memory into
@ -116,17 +115,17 @@ enum commands {
/* Since the 3c507 maps the shared memory window so that the last byte is
at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or
48K corresponding to window sizes of 64K, 48K, 32K and 16K respectively.
48K corresponding to window sizes of 64K, 48K, 32K and 16K respectively.
We can account for this be setting the 'SBC Base' entry in the ISCP table
below for all the 16 bit offset addresses, and also adding the 'SCB Base'
value to all 24 bit physical addresses (in the SCP table and the TX and RX
Buffer Descriptors).
-Mark
-Mark
*/
/*
What follows in 'init_words[]' is the "program" that is downloaded to the
82586 memory. It's mostly tables and command blocks, and starts at the
82586 memory. It's mostly tables and command blocks, and starts at the
reset address 0xfffff6. This is designed to be similar to the EtherExpress,
thus the unusual location of the SCB at 0x0008.
@ -152,17 +151,17 @@ Buffer Descriptors).
#define DUMP_DATA 0x56 /* A 170 byte buffer for dump and Set-MC into. */
#define TX_BUF_START 0x0100
#define TX_BUF_SIZE (1518+14+20+16) /* packet+header+TBD */
#define TX_BUF_SIZE (1518+14+20+16) /* packet+header+TBD */
#define RX_BUF_START 0x1000
#define RX_BUF_SIZE (1518+14+18) /* packet+header+RBD */
#define RX_BUF_SIZE (1518+14+18) /* packet+header+RBD */
#define RX_BUF_END (mem_end - mem_start - 20)
/*
That's it: only 86 bytes to set up the beast, including every extra
command available. The 170 byte buffer at DUMP_DATA is shared between the
Dump command (called only by the diagnostic program) and the SetMulticastList
command.
command.
To complete the memory setup you only have to write the station address at
SA_OFFSET and create the Tx & Rx buffer lists.
@ -223,7 +222,7 @@ static unsigned short init_words[] = {
SET_MC_CMD, /* Next command. */
0xaa00,0xb000,0x0bad, /* Station address (to be filled in) */
/* 0x0030: NOP, looping back to itself. Point to first Tx buffer to Tx. */
/* 0x0030: NOP, looping back to itself. Point to first Tx buffer to Tx. */
0, CmdNOp, IDLELOOP, 0 /* pad */,
/* 0x0038: A unused Time-Domain Reflectometer command. */
@ -336,7 +335,7 @@ RESET - Reset adapter
static void i82586_reset(struct nic *nic)
{
long time;
unsigned long time;
#ifdef ETHERBOOT32
unsigned short *shmem = (short *)mem_start;
#endif
@ -382,14 +381,14 @@ static void i82586_reset(struct nic *nic)
time = currticks() + TICKS_PER_SEC; /* allow 1 second to init */
while (
#ifdef ETHERBOOT16
read_mem(mem_start, shmem),
read_mem(mem_start, shmem),
#endif
shmem[iSCB_STATUS>>1] == 0)
shmem[iSCB_STATUS>>1] == 0)
{
if (currticks() > time)
{
printf("i82586 initialisation timed out with status %x, cmd %x\n",
shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
break;
}
}
@ -405,18 +404,18 @@ static void i82586_reset(struct nic *nic)
read_mem(mem_start, shmem);
#endif
printf("i82586 status %x, cmd %x\n",
shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
#endif
}
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
POLL - Wait for a frame
***************************************************************************/
static int i82586_poll(struct nic *nic)
{
int status;
unsigned short rfd_cmd, next_rx_frame, data_buffer_addr,
frame_status, pkt_len;
frame_status, pkt_len;
#ifdef ETHERBOOT32
unsigned short *shmem = (short *)mem_start + rx_head;
#endif
@ -427,9 +426,9 @@ static int i82586_poll(struct nic *nic)
/* return true if there's an ethernet packet ready to read */
if (
#ifdef ETHERBOOT16
read_mem(mem_start + rx_head, shmem),
read_mem(mem_start + rx_head, shmem),
#endif
((frame_status = shmem[0]) & 0x8000) == 0)
((frame_status = shmem[0]) & 0x8000) == 0)
return (0); /* nope */
rfd_cmd = shmem[1];
next_rx_frame = shmem[2];
@ -437,7 +436,7 @@ static int i82586_poll(struct nic *nic)
pkt_len = shmem[11];
status = 0;
if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22
|| (pkt_len & 0xC000) != 0xC000)
|| (pkt_len & 0xC000) != 0xC000)
printf("\nRx frame corrupt, discarded");
else if ((frame_status & 0x2000) == 0)
printf("\nRx frame had error");
@ -476,14 +475,14 @@ static int i82586_poll(struct nic *nic)
}
/**************************************************************************
TRANSMIT - Transmit a frame
***************************************************************************/
TRANSMIT - Transmit a frame
***************************************************************************/
static void i82586_transmit(
struct nic *nic,
char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
struct nic *nic,
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
const char *p) /* Packet */
{
Address bptr;
unsigned short type, z;
@ -545,9 +544,9 @@ char *p) /* Packet */
/* Wait for transmit completion */
while (
#ifdef ETHERBOOT16
read_mem(mem_start + TX_BUF_START, shmem),
read_mem(mem_start + TX_BUF_START, shmem),
#endif
(shmem[0] & 0x2000) == 0)
(shmem[0] & 0x2000) == 0)
;
/* Change the offset in the IDLELOOP back and
change the final loop to point here */
@ -564,8 +563,8 @@ char *p) /* Packet */
}
/**************************************************************************
DISABLE - Turn off ethernet interface
***************************************************************************/
DISABLE - Turn off ethernet interface
***************************************************************************/
static void i82586_disable(struct nic *nic)
{
#ifdef ETHERBOOT32
@ -816,7 +815,7 @@ struct nic *ni5210_probe(struct nic *nic, unsigned short *probe_addrs)
* Code to download to I186 in EXOS205
*/
static unsigned char exos_i186_init[] =
static unsigned char exos_i186_init[] =
{
0x08,0x00,0x14,0x00,0x00,0x00,0xaa,0xfa,0x33,0xc0,0xba,0xfe,0xff,0xef,0xb8,0xf8,
0xff,0xe7,0xa0,0xb8,0x7c,0x00,0xe7,0xa4,0xb8,0xbc,0x80,0xe7,0xa8,0x8c,0xc8,0x8e,

View file

@ -1,18 +0,0 @@
/* 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 */

View file

@ -16,9 +16,13 @@ Ken Yap, July 1997
#include "etherboot.h"
/* to get the interface to the body of the program */
#include "nic.h"
#ifdef INCLUDE_LANCE
#include "pci.h"
#endif
#include "cards.h"
/* Offsets from base I/O address */
#if defined(INCLUDE_NE2100) || defined(INCLUDE_LANCEPCI)
#if defined(INCLUDE_NE2100) || defined(INCLUDE_LANCE)
#define LANCE_ETH_ADDR 0x0
#define LANCE_DATA 0x10
#define LANCE_ADDR 0x12
@ -41,7 +45,7 @@ struct lance_init_block
unsigned char phys_addr[6];
unsigned long filter[2];
Address rx_ring;
Address tx_ring;
Address tx_ring;
};
struct lance_rx_head
@ -75,9 +79,7 @@ struct lance_interface
#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
@ -85,31 +87,25 @@ struct lance_interface
static struct lance_chip_type
{
int id_number;
char *name;
const 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},
LANCE_ENABLE_AUTOSELECT},
{0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
LANCE_ENABLE_AUTOSELECT},
{0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */
LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
LANCE_HAS_MISSED_FRAME},
LANCE_ENABLE_AUTOSELECT},
/* 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},
LANCE_ENABLE_AUTOSELECT},
{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},
LANCE_ENABLE_AUTOSELECT},
{0x0, "PCnet (unknown)",
LANCE_ENABLE_AUTOSELECT},
};
/* Define a macro for converting program addresses to real addresses */
@ -125,9 +121,16 @@ 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];
/* additional 8 bytes for 8-byte alignment space */
#ifndef USE_INTERNAL_BUFFER
#define lance ((char *)0x10000 - (sizeof(struct lance_interface)+8))
#else
static char lance[sizeof(struct lance_interface)+8];
#endif
#ifndef INCLUDE_LANCE
/* DMA defines and helper routines */
/* DMA controller registers */
@ -183,6 +186,7 @@ static void set_dma_mode(unsigned int dmanr, char mode)
else
outb_p(mode | (dmanr&3), DMA2_MODE_REG);
}
#endif /* !INCLUDE_LANCE */
/**************************************************************************
RESET - Reset adapter
@ -202,7 +206,8 @@ static void lance_reset(struct nic *nic)
/* This is 79C960 specific; Turn on auto-select of media
(AUI, BNC). */
outw(0x2, ioaddr+LANCE_ADDR);
outw(0x2, ioaddr+LANCE_BUS_IF);
/* Don't touch 10base2 power bit. */
outw(inw(ioaddr+LANCE_BUS_IF) | 0x2, ioaddr+LANCE_BUS_IF);
}
/* Re-initialise the LANCE, and start it when done. */
/* Set station address */
@ -269,10 +274,10 @@ TRANSMIT - Transmit a frame
***************************************************************************/
static void lance_transmit(
struct nic *nic,
char *d, /* Destination */
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
const char *p) /* Packet */
{
unsigned long time;
@ -312,18 +317,26 @@ static void lance_transmit(
static void lance_disable(struct nic *nic)
{
#ifndef INCLUDE_LANCE
disable_dma(dma);
#endif
}
#ifdef INCLUDE_LANCE
static int lance_probe1(struct nic *nic, struct pci_device *pci)
#else
static int lance_probe1(struct nic *nic)
#endif
{
int reset_val, lance_version, i;
int reset_val, lance_version;
unsigned int i;
Address l;
short dma_channels;
static char dmas[] = { 5, 6, 7, 3 };
static const char dmas[] = { 5, 6, 7, 3 };
reset_val = inw(ioaddr+LANCE_RESET);
#ifdef INCLUDE_NE2100
outw(reset_val, ioaddr+LANCE_RESET);
#if 1 /* Klaus Espenlaub -- was #ifdef INCLUDE_NE2100*/
outw(0x0, ioaddr+LANCE_ADDR); /* Switch to window 0 */
if (inw(ioaddr+LANCE_DATA) != 0x4)
return (-1);
@ -363,6 +376,7 @@ static int lance_probe1(struct nic *nic)
outw(0x915, ioaddr+LANCE_DATA);
outw(0x0, ioaddr+LANCE_ADDR);
(void)inw(ioaddr+LANCE_ADDR);
#ifndef INCLUDE_LANCE
/* now probe for DMA channel */
dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0xf) |
(inb(DMA2_STAT_REG) & 0xf0);
@ -392,6 +406,9 @@ static int lance_probe1(struct nic *nic)
dma = 0;
printf("\n%s base 0x%x, DMA %d, addr ",
chip_table[lance_version].name, ioaddr, dma);
#else
printf(" %s base 0x%x, addr ", chip_table[lance_version].name, ioaddr);
#endif
/* Get station address */
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
{
@ -400,6 +417,13 @@ static int lance_probe1(struct nic *nic)
printf(":");
}
putchar('\n');
if (chip_table[chip_version].flags & LANCE_ENABLE_AUTOSELECT) {
/* Turn on auto-select of media (10baseT or BNC) so that the
* user watch the LEDs. */
outw(0x0002, ioaddr+LANCE_ADDR);
/* Don't touch 10base2 power bit. */
outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);
}
return (lance_version);
}
@ -407,8 +431,8 @@ static int lance_probe1(struct nic *nic)
PROBE - Look for an adapter, this routine's visible to the outside
***************************************************************************/
#ifdef INCLUDE_LANCEPCI
struct nic *lancepci_probe(struct nic *nic, unsigned short *probe_addrs)
#ifdef INCLUDE_LANCE
struct nic *lancepci_probe(struct nic *nic, unsigned short *probe_addrs, struct pci_device *pci)
#endif
#ifdef INCLUDE_NE2100
struct nic *ne2100_probe(struct nic *nic, unsigned short *probe_addrs)
@ -425,18 +449,30 @@ struct nic *ni6510_probe(struct nic *nic, unsigned short *probe_addrs)
probe_addrs = io_addrs;
for (p = probe_addrs; (ioaddr = *p) != 0; ++p)
{
char offset15, offset14 = inb(ioaddr + 14);
char offset15, offset14 = inb(ioaddr + 14);
short pci_cmd;
#ifdef INCLUDE_NE2100
if ((offset14 == 0x52 || offset14 == 0x57) &&
((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44))
if (lance_probe1(nic) >= 0)
break;
#endif
#ifdef INCLUDE_NI6510
if ((offset14 == 0x00 || offset14 == 0x52) &&
((offset15 = inb(ioaddr + 15)) == 0x55 || offset15 == 0x44))
#endif
if (lance_probe1(nic) >= 0)
break;
#endif
#ifdef INCLUDE_LANCE
pcibios_read_config_word(0, pci->devfn, PCI_COMMAND, &pci_cmd);
if (!(pci_cmd & PCI_COMMAND_MASTER)) {
pci_cmd |= PCI_COMMAND_MASTER;
pcibios_write_config_word(0, pci->devfn, PCI_COMMAND, pci_cmd);
}
if (lance_probe1(nic, pci) >= 0)
break;
#endif
}
/* if board found */
if (ioaddr != 0)

View file

@ -1,4 +1,4 @@
#ifndef _ASM_IO_H
#ifndef _ASM_IO_H
#define _ASM_IO_H
/*
@ -25,42 +25,18 @@
* Linus
*/
#ifdef SLOW_IO_BY_JUMPING
#ifdef SLOW_IO_BY_JUMPING
#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
#else
#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
#endif
#ifdef REALLY_SLOW_IO
#ifdef REALLY_SLOW_IO
#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
#else
#define SLOW_DOWN_IO __SLOW_DOWN_IO
#endif
/*
* Change virtual addresses to physical addresses and vv.
* These are trivial on the 1:1 Linux/i386 mapping (but if we ever
* make the kernel segment mapped at 0, we need to do translation
* on the i386 as well)
*/
extern inline unsigned long virt_to_phys(volatile void * address);
extern inline unsigned long virt_to_phys(volatile void * address)
{
return (unsigned long) address;
}
extern inline void * phys_to_virt(unsigned long address);
extern inline void * phys_to_virt(unsigned long address)
{
return (void *) address;
}
/*
* IO bus memory addresses are also 1:1 with the physical address
*/
#define virt_to_bus virt_to_phys
#define bus_to_virt phys_to_virt
/*
* readX/writeX() are used to access memory mapped devices. On some
* architectures the memory mapped IO stuff needs to be accessed
@ -90,7 +66,7 @@ extern inline void * phys_to_virt(unsigned long address)
*/
#define __OUT1(s,x) \
extern inline void __out##s(unsigned x value, unsigned short port); \
extern 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) \
@ -102,42 +78,34 @@ __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 __IN1(s,x) \
extern unsigned x __in##s(unsigned short port); \
extern inline unsigned x __in##s(unsigned short port) { unsigned x _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 __IN(s,s1,x,i...) \
__IN1(s,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); return _v; } \
__IN1(s##c,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); return _v; } \
__IN1(s##_p,x) __IN2(s,s1,"w") : "=a" (_v) : "d" (port) ,##i ); SLOW_DOWN_IO; return _v; } \
__IN1(s##c_p,x) __IN2(s,s1,"") : "=a" (_v) : "id" (port) ,##i ); SLOW_DOWN_IO; return _v; }
#define __INS(s) \
extern inline void ins##s(unsigned short port, void * addr, unsigned long count); \
extern void ins##s(unsigned short port, void * addr, unsigned long count); \
extern inline void ins##s(unsigned short port, void * addr, unsigned long count) \
{ __asm__ __volatile__ ("cld ; rep ; ins" #s \
: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
#define __OUTS(s) \
extern inline void outs##s(unsigned short port, const void * addr, unsigned long count); \
extern void outs##s(unsigned short port, const void * addr, unsigned long count); \
extern inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
{ __asm__ __volatile__ ("cld ; rep ; outs" #s \
: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
#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
__IN(b,"", char)
__IN(w,"",short)
__IN(l,"", long)
__OUT(b,"b",char)
__OUT(w,"w",short)

View file

@ -1,9 +1,9 @@
/*
* Taken from Linux /usr/include/asm/string.h
* All except memcpy, memset and memcmp removed.
* All except memcpy, memmove, memset and memcmp removed.
*/
#ifndef _I386_STRING_H_
#ifndef _I386_STRING_H_
#define _I386_STRING_H_
/*
@ -19,9 +19,15 @@
* consider these trivial functions to be PD.
*/
#ifndef __FreeBSD__
typedef int size_t;
#endif
extern void *__memcpy(void * to, const void * from, size_t n);
extern void *__constant_memcpy(void * to, const void * from, size_t n);
extern void *memmove(void * dest,const void * src, size_t n);
extern void *__memset_generic(void * s, char c,size_t count);
extern void *__constant_c_memset(void * s, unsigned long c, size_t count);
extern void *__constant_c_and_count_memset(void * s, unsigned long pattern, size_t count);
extern inline void * __memcpy(void * to, const void * from, size_t n)
{
@ -108,7 +114,7 @@ __asm__ __volatile__( \
default: COMMON("\n\tmovsw\n\tmovsb"); return to;
}
}
#undef COMMON
}
@ -183,7 +189,7 @@ __asm__ __volatile__(
: "=&c" (d0), "=&D" (d1)
:"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
:"memory");
return (s);
return (s);
}
/*
@ -225,7 +231,7 @@ __asm__ __volatile__("cld\n\t" \
default: COMMON("\n\tstosw\n\tstosb"); return s;
}
}
#undef COMMON
}
@ -242,7 +248,7 @@ __asm__ __volatile__("cld\n\t" \
#define __HAVE_ARCH_MEMSET
#define memset(s, c, count) \
(__builtin_constant_p(c) ? \
__memset((s),(c),(count)) : \
__constant_c_x_memset((s),(c),(count)) : \
__memset((s),(c),(count)))
#endif

View file

@ -17,13 +17,23 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Based on "src/main.c" in etherboot-4.4.2. */
/* Based on "src/main.c" in etherboot-4.5.8. */
/**************************************************************************
ETHERBOOT - BOOTP/TFTP Bootstrap Program
Author: Martin Renters
Date: Dec/93
Literature dealing with the network protocols:
ARP - RFC826
RARP - RFC903
UDP - RFC768
BOOTP - RFC951, RFC2132 (vendor extensions)
DHCP - RFC2131, RFC2132 (options)
TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
**************************************************************************/
@ -32,8 +42,6 @@ Author: Martin Renters
#include <etherboot.h>
#include <nic.h>
#include <netboot_config.h>
struct arptable_t arptable[MAX_ARP];
/* Set if the user pushes Control-C. */
@ -67,7 +75,7 @@ static char rfc1533_cookie[5] = {RFC1533_COOKIE, RFC1533_END};
static char rfc1533_cookie[] = {RFC1533_COOKIE};
static char rfc1533_end[] = {RFC1533_END};
static char dhcpdiscover[] =
static const char dhcpdiscover[] =
{
RFC2132_MSG_TYPE, 1, DHCPDISCOVER,
RFC2132_MAX_SIZE, 2, 2, 64,
@ -75,7 +83,7 @@ static char dhcpdiscover[] =
RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH
};
static char dhcprequest[] =
static const char dhcprequest[] =
{
RFC2132_MSG_TYPE, 1, DHCPREQUEST,
RFC2132_SRV_ID, 4, 0, 0, 0, 0,
@ -83,13 +91,21 @@ static char dhcprequest[] =
RFC2132_MAX_SIZE, 2, 2, 64,
/* request parameters */
RFC2132_PARAM_LIST,
#ifdef IMAGE_FREEBSD
/* 4 standard + 4 vendortags + 8 motd + 16 menu items */
4 + 4 + 8 + 16,
#else
/* 4 standard + 3 vendortags + 8 motd + 16 menu items */
4 + 3 + 8 + 16,
#endif
/* Standard parameters */
RFC1533_NETMASK, RFC1533_GATEWAY,
RFC1533_HOSTNAME, RFC1533_EXTENSIONPATH,
/* Etherboot vendortags */
RFC1533_VENDOR_MAGIC, RFC1533_VENDOR_HOWTO,
RFC1533_VENDOR_MAGIC,
#ifdef IMAGE_FREEBSD
RFC1533_VENDOR_HOWTO,
#endif
RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION,
/* 8 MOTD entries */
RFC1533_VENDOR_MOTD,
@ -121,7 +137,7 @@ static char dhcprequest[] =
#endif /* ! NO_DHCP_SUPPORT */
static char broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static const char broadcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
void
print_network_configuration (void)
@ -170,8 +186,8 @@ default_netmask (void)
UDP_TRANSMIT - Send a UDP datagram
**************************************************************************/
int
udp_transmit (unsigned long destip, unsigned srcsock, unsigned destsock,
int len, char *buf)
udp_transmit (unsigned long destip, unsigned int srcsock,
unsigned int destsock, int len, const void *buf)
{
struct iphdr *ip;
struct udphdr *udp;
@ -180,7 +196,7 @@ udp_transmit (unsigned long destip, unsigned srcsock, unsigned destsock,
int retry;
ip = (struct iphdr *) buf;
udp = (struct udphdr *) (buf + sizeof (struct iphdr));
udp = (struct udphdr *) ((unsigned long) buf + sizeof (struct iphdr));
ip->verhdrlen = 0x45;
ip->service = 0;
ip->len = htons (len);
@ -237,9 +253,20 @@ udp_transmit (unsigned long destip, unsigned srcsock, unsigned destsock,
grub_memset (arpreq.thwaddr, 0, ETHER_ADDR_SIZE);
grub_memmove (arpreq.tipaddr, (char *) &destip, sizeof (in_addr));
for (retry = 0; retry < MAX_ARP_RETRIES; rfc951_sleep (++retry))
for (retry = 1; retry <= MAX_ARP_RETRIES; retry++)
{
eth_transmit (broadcast, ARP, sizeof (arpreq), (char *) &arpreq);
eth_transmit (broadcast, ARP, sizeof (arpreq), &arpreq);
if (await_reply (AWAIT_ARP, arpentry, arpreq.tipaddr, TIMEOUT))
goto xmit;
if (ip_abort)
return 0;
rfc951_sleep (retry);
/* We have slept for a while - the packet may
* have arrived by now. If not, we have at
* least some room in the Rx buffer for the
* next reply. */
if (await_reply (AWAIT_ARP, arpentry, arpreq.tipaddr, 0))
goto xmit;
@ -264,28 +291,38 @@ static int
tftp (char *name, int (*fnc) (unsigned char *, int, int, int))
{
int retry = 0;
static unsigned short isocket = 2000;
unsigned short osocket;
static unsigned short iport = 2000;
unsigned short oport;
unsigned short len, block = 0, prevblock = 0;
int bcounter = 0;
struct tftp_t *tr;
struct tftp_t tp;
int rc;
int packetsize = TFTP_DEFAULTSIZE_PACKET;
/* Clear out the Rx queue first. It contains nothing of interest,
* except possibly ARP requests from the DHCP/TFTP server. We use
* polling throughout Etherboot, so some time may have passed since we
* last polled the receive queue, which may now be filled with
* broadcast packets. This will cause the reply to the packets we are
* about to send to be lost immediately. Not very clever. */
await_reply (AWAIT_QDRAIN, 0, NULL, 0);
tp.opcode = htons (TFTP_RRQ);
len = (grub_sprintf ((char *)tp.u.rrq, "%s%coctet%cblksize%c%d",
name, 0, 0, 0, TFTP_MAX_PACKET)
+ TFTP_MIN_PACKET + 1);
if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++isocket, TFTP,
len, (char *) &tp))
if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
TFTP_PORT, len, &tp))
return 0;
for (;;)
{
#ifdef CONGESTED
if (! await_reply (AWAIT_TFTP, isocket, NULL, (block ? TFTP_REXMT : 0)))
if (! await_reply (AWAIT_TFTP, iport, NULL,
(block ? TFTP_REXMT : TIMEOUT)))
#else
if (! await_reply (AWAIT_TFTP, isocket, NULL, 0))
if (! await_reply (AWAIT_TFTP, iport, NULL, TIMEOUT))
#endif
{
if (! block && retry++ < MAX_TFTP_RETRIES)
@ -293,7 +330,7 @@ tftp (char *name, int (*fnc) (unsigned char *, int, int, int))
/* Maybe initial request was lost. */
rfc951_sleep (retry);
if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
++isocket, TFTP, len, (char *) &tp))
++iport, TFTP_PORT, len, &tp))
return 0;
continue;
@ -307,8 +344,8 @@ tftp (char *name, int (*fnc) (unsigned char *, int, int, int))
grub_printf ("<REXMT>\n");
#endif
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
isocket, osocket,
TFTP_MIN_PACKET, (char *)&tp);
iport, oport,
TFTP_MIN_PACKET, &tp);
continue;
}
#endif
@ -362,8 +399,8 @@ tftp (char *name, int (*fnc) (unsigned char *, int, int, int))
"RFC1782 error")
+ TFTP_MIN_PACKET + 1);
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
isocket, ntohs (tr->udp.src),
len, (char *) &tp);
iport, ntohs (tr->udp.src),
len, &tp);
return 0;
}
}
@ -388,27 +425,28 @@ tftp (char *name, int (*fnc) (unsigned char *, int, int, int))
/* Neither TFTP_OACK nor TFTP_DATA. */
break;
if (block && (block != prevblock+1))
/* Block order. */
if ((block || bcounter) && (block != prevblock + 1))
/* Block order should be continuous */
tp.u.ack.block = htons (block = prevblock);
/* Should be continuous. */
tp.opcode = htons (TFTP_ACK);
osocket = ntohs (tr->udp.src);
oport = ntohs (tr->udp.src);
/* Ack. */
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, isocket,
osocket, TFTP_MIN_PACKET, (char *) &tp);
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr, iport,
oport, TFTP_MIN_PACKET, &tp);
/* Retransmission or OACK. */
if (block <= prevblock)
/* Don't process. */
if ((unsigned short) (block - prevblock) != 1)
/* Retransmission or OACK, don't process via callback
* and don't change the value of prevblock. */
continue;
prevblock = block;
/* Is it the right place to zero the timer? */
retry = 0;
if ((rc = fnc (tr->u.data.download, block, len, len < packetsize)) >= 0)
if ((rc = fnc (tr->u.data.download,
++bcounter, len, len < packetsize)) >= 0)
return rc;
/* End of data. */
@ -453,9 +491,9 @@ rarp (void)
for (retry = 0; retry < MAX_ARP_RETRIES; rfc951_sleep (++retry))
{
eth_transmit (broadcast, RARP, sizeof (rarpreq), (char *) &rarpreq);
eth_transmit (broadcast, RARP, sizeof (rarpreq), &rarpreq);
if (await_reply (AWAIT_RARP, 0, rarpreq.shwaddr, 0))
if (await_reply (AWAIT_RARP, 0, rarpreq.shwaddr, TIMEOUT))
break;
if (ip_abort)
@ -516,23 +554,17 @@ bootp (void)
for (retry = 0; retry < MAX_BOOTP_RETRIES;)
{
/*
* Discard all received packets - we have no requests
* outstanding. It happened too often that the reply sent
* by the BOOTP server caused a RX buffer overrun (which for
* most cards - especially the cheap ones with a small
* receive buffer - is handled by discarding the whole
* receive buffer contents). An even cruder way to solve
* the problem would be to discard all packets while in
* rfc951_sleep(), but this may have affected future changes
* to the etherboot implementation.
*/
while (eth_poll ())
/* Nothing */
;
/* Clear out the Rx queue first. It contains nothing of
* interest, except possibly ARP requests from the DHCP/TFTP
* server. We use polling throughout Etherboot, so some time
* may have passed since we last polled the receive queue,
* which may now be filled with broadcast packets. This will
* cause the reply to the packets we are about to send to be
* lost immediately. Not very clever. */
await_reply (AWAIT_QDRAIN, 0, NULL, 0);
udp_transmit (IP_BROADCAST, 0, BOOTP_SERVER,
sizeof (struct bootp_t), (char *) &bp);
sizeof (struct bootp_t), &bp);
#ifdef T509HACK
if (flag)
{
@ -542,13 +574,13 @@ bootp (void)
#endif /* T509HACK */
#ifdef NO_DHCP_SUPPORT
if (await_reply (AWAIT_BOOTP, 0, NULL, 0))
if (await_reply (AWAIT_BOOTP, 0, NULL, TIMEOUT))
{
network_ready = 1;
return 1;
}
#else /* ! NO_DHCP_SUPPORT */
if (await_reply (AWAIT_BOOTP, 0, NULL, 0))
if (await_reply (AWAIT_BOOTP, 0, NULL, TIMEOUT))
{
if (dhcp_reply == DHCPOFFER)
{
@ -566,9 +598,9 @@ bootp (void)
for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;)
{
udp_transmit (IP_BROADCAST, 0, BOOTP_SERVER,
sizeof (struct bootp_t), (char *) &bp);
sizeof (struct bootp_t), &bp);
dhcp_reply = 0;
if (await_reply (AWAIT_BOOTP, 0, NULL, 0))
if (await_reply (AWAIT_BOOTP, 0, NULL, TIMEOUT))
if (dhcp_reply == DHCPACK)
{
network_ready = 1;
@ -607,35 +639,26 @@ bootp (void)
AWAIT_REPLY - Wait until we get a response for our request
**************************************************************************/
int
await_reply (int type, int ival, char *ptr, int timeout)
await_reply (int type, int ival, void *ptr, int timeout)
{
unsigned long time;
struct iphdr *ip;
struct udphdr *udp;
struct arprequest *arpreply;
struct bootp_t *bootpreply;
struct rpc_t *rpc;
unsigned short ptype;
int protohdrlen = (ETHER_HDR_SIZE + sizeof (struct iphdr)
+ sizeof (struct udphdr));
unsigned int protohdrlen = (ETHER_HDR_SIZE + sizeof (struct iphdr)
+ sizeof (struct udphdr));
/* Clear the abort flag. */
ip_abort = 0;
#ifdef CONGESTED
time = currticks () + (timeout ? timeout : TIMEOUT);
#else
time = currticks () + TIMEOUT;
#endif
while (time > currticks ())
/* The timeout check is done below. The timeout is only checked if
* there is no packet in the Rx queue. This assumes that eth_poll()
* needs a negligible amount of time. */
for (;;)
{
/* If Control-C is pushed, return immediately. */
if (checkkey () != -1 && ASCII_CHAR (getkey ()) == CTRL_C)
{
ip_abort = 1;
return 0;
}
if (eth_poll ())
{
/* We have something! */
@ -686,7 +709,7 @@ await_reply (int type, int ival, char *ptr, int timeout)
ETHER_ADDR_SIZE);
eth_transmit (arpreply->thwaddr, ARP,
sizeof (struct arprequest),
(char *) arpreply);
arpreply);
#ifdef MDEBUG
grub_memmove (&tmp, arpreply->tipaddr, sizeof (in_addr));
grub_printf ("Sent ARP reply to: %x\n", tmp);
@ -696,6 +719,11 @@ await_reply (int type, int ival, char *ptr, int timeout)
continue;
}
if (type == AWAIT_QDRAIN)
{
continue;
}
/* Check for RARP - No IP hdr. */
if (type == AWAIT_RARP
&& nic.packetlen >= ETHER_HDR_SIZE + sizeof (struct arprequest)
@ -761,13 +789,13 @@ await_reply (int type, int ival, char *ptr, int timeout)
grub_memset (arptable[ARP_GATEWAY].node, 0, ETHER_ADDR_SIZE);
/* GRUB doesn't autoload any kernel image. */
#if 0
#ifndef GRUB
if (bootpreply->bp_file[0])
{
grub_memmove (kernel_buf, bootpreply->bp_file, 128);
kernel = kernel_buf;
}
#endif
#endif /* ! GRUB */
grub_memmove ((char *) BOOTP_DATA_ADDR, (char *) bootpreply,
sizeof (struct bootpd_t));
@ -785,9 +813,24 @@ await_reply (int type, int ival, char *ptr, int timeout)
/* TFTP ? */
if (type == AWAIT_TFTP && ntohs (udp->dest) == ival)
return 1;
}
else
{
/* Check for abort key only if the Rx queue is empty -
* as long as we have something to process, don't
* assume that something failed. It is unlikely that
* we have no processing time left between packets. */
if (checkkey () != -1 && ASCII_CHAR (getkey ()) == CTRL_C)
{
ip_abort = 1;
return 0;
}
/* RPC */
rpc = (struct rpc_t *) &nic.packet[ETHER_HDR_SIZE];
/* Do the timeout after at least a full queue walk. */
if ((timeout == 0) || (currticks() > time))
{
break;
}
}
}
@ -802,7 +845,7 @@ decode_rfc1533 (unsigned char *p, int block, int len, int eof)
{
static unsigned char *extdata = NULL, *extend = NULL;
unsigned char *extpath = NULL;
unsigned char *end;
unsigned char *endp;
if (block == 0)
{
@ -823,7 +866,7 @@ decode_rfc1533 (unsigned char *p, int block, int len, int eof)
return 0;
p += 4;
end = p + len;
endp = p + len;
}
else
{
@ -852,12 +895,12 @@ decode_rfc1533 (unsigned char *p, int block, int len, int eof)
}
p = extdata;
end = extend;
endp = extend;
}
if (eof)
{
while (p < end)
while (p < endp)
{
unsigned char c = *p;
@ -868,7 +911,7 @@ decode_rfc1533 (unsigned char *p, int block, int len, int eof)
}
else if (c == RFC1533_END)
{
end_of_rfc1533 = end = p;
end_of_rfc1533 = endp = p;
continue;
}
else if (c == RFC1533_NETMASK)
@ -898,23 +941,19 @@ decode_rfc1533 (unsigned char *p, int block, int len, int eof)
#endif /* ! NO_DHCP_SUPPORT */
/* GRUB needs not to use any vendor-specific extension. */
#if 0
#ifndef GRUB
else if (c == RFC1533_VENDOR_MAGIC
# if !defined(AOUT_IMAGE) && !defined(ELF_IMAGE) /* since FreeBSD uses tag 128 for swap definition */
&& TAG_LEN (p) >= 6 &&
!memcmp (p + 2, vendorext_magic, 4) &&
# ifndef IMAGE_FREEBSD /* since FreeBSD uses tag 128 for swap definition */
&& TAG_LEN(p) >= 6 &&
!memcmp(p+2,vendorext_magic,4) &&
p[6] == RFC1533_VENDOR_MAJOR
# endif
)
)
vendorext_isvalid++;
# if defined(AOUT_IMAGE) || defined(ELF_IMAGE)
else if (c == RFC1533_VENDOR_HOWTO)
{
howto = ((p[2] * 256 + p[3]) * 256 + p[4]) * 256 + p[5];
/*
printf("Howto %X %d,%x %x %x %x\n",howto,TAGLEN(p),p[2],p[3],p[4],p[5]);
*/
}
# ifdef IMAGE_FREEBSD
else if (c == RFC1533_VENDOR_HOWTO) {
freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
}
# endif
# ifdef IMAGE_MENU
else if (c == RFC1533_VENDOR_MNUOPTS)
@ -936,17 +975,19 @@ decode_rfc1533 (unsigned char *p, int block, int len, int eof)
# endif
else
{
/* printf("Unknown RFC1533-tag ");
for(q=p;q<p+2+TAG_LEN(p);q++)
printf("%x ",*q);
putchar('\n'); */
# if 0
printf("Unknown RFC1533-tag ");
for(q=p;q<p+2+TAG_LEN(p);q++)
printf("%x ",*q);
putchar('\n');
# endif
}
#endif /* 0 */
#endif /* ! GRUB */
p += TAG_LEN (p) + 2;
}
extdata = extend = end;
extdata = extend = endp;
/* Perhaps we can eliminate this because we doesn't require so
much information, but I leave this alone. */
@ -988,8 +1029,14 @@ void
rfc951_sleep (int exp)
{
static long seed = 0;
long q, tmo;
long q;
unsigned long tmo;
#ifdef BACKOFF_LIMIT
if (exp > BACKOFF_LIMIT)
exp = BACKOFF_LIMIT;
#endif
if (! seed)
/* Initialize linear congruential generator. */
seed = (currticks () + *(long *) &arptable[ARP_CLIENT].node
@ -1013,3 +1060,32 @@ rfc951_sleep (int exp)
if (checkkey () != -1 && ASCII_CHAR (getkey ()) == CTRL_C)
break;
}
/**************************************************************************
CLEANUP_NET - shut down networking
**************************************************************************/
void
cleanup_net (void)
{
if (network_ready)
{
#ifdef DOWNLOAD_PROTO_NFS
nfs_umountall (ARP_SERVER);
#endif
eth_disable ();
network_ready = 0;
}
}
#ifndef GRUB
/**************************************************************************
CLEANUP - shut down etherboot so that the OS may be called right away
**************************************************************************/
void
cleanup (void)
{
#if defined(ANSIESC) && defined(CONSOLE_CRT)
ansi_reset ();
#endif
}
#endif /* ! GRUB */

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Based on "src/misc.c" in etherboot-4.4.2. */
/* Based on "src/misc.c" in etherboot-4.5.8. */
/**************************************************************************
MISC Support Routines
@ -30,7 +30,7 @@ SLEEP
**************************************************************************/
void sleep(int secs)
{
long tmo;
unsigned long tmo;
for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; )
/* Nothing */;
@ -45,15 +45,14 @@ void twiddle()
static int count=0;
static char tiddles[]="-\\|/";
unsigned long ticks;
if ((ticks = currticks()) < lastticks)
if ((ticks = currticks()) == lastticks)
return;
lastticks = ticks+1;
lastticks = ticks;
putchar(tiddles[(count++)&3]);
putchar('\b');
}
#if 0
#ifdef ETHERBOOT32
#ifndef GRUB
/**************************************************************************
STRCASECMP (not entirely correct, but this will do for our purposes)
**************************************************************************/
@ -63,7 +62,6 @@ int strcasecmp(a,b)
while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
return((*a & ~0x20) - (*b & ~0x20));
}
#endif /* ETHERBOOT32 */
/**************************************************************************
PRINTF and friends
@ -78,9 +76,7 @@ PRINTF and friends
%I - Internet address in x.x.x.x notation
**************************************************************************/
static char hex[]="0123456789ABCDEF";
char *do_printf(buf, fmt, dp)
char *buf, *fmt;
int *dp;
static char *do_printf(char *buf, const char *fmt, const int *dp)
{
register char *p;
char tmp[16];
@ -89,9 +85,9 @@ char *do_printf(buf, fmt, dp)
fmt++;
if (*fmt == 'X') {
long *lp = (long *)dp;
const long *lp = (const long *)dp;
register long h = *lp++;
dp = (int *)lp;
dp = (const int *)lp;
*(buf++) = hex[(h>>28)& 0x0F];
*(buf++) = hex[(h>>24)& 0x0F];
*(buf++) = hex[(h>>20)& 0x0F];
@ -131,9 +127,9 @@ char *do_printf(buf, fmt, dp)
long l;
unsigned char c[4];
} u;
long *lp = (long *)dp;
const long *lp = (const long *)dp;
u.l = *lp++;
dp = (int *)lp;
dp = (const int *)lp;
buf = sprintf(buf,"%d.%d.%d.%d",
u.c[0], u.c[1], u.c[2], u.c[3]);
}
@ -150,30 +146,25 @@ char *do_printf(buf, fmt, dp)
return(buf);
}
char *sprintf(buf, fmt, data)
char *fmt, *buf;
int data;
char *sprintf(char *buf, const char *fmt, ...)
{
return(do_printf(buf,fmt, &data));
return do_printf(buf, fmt, ((const int *)&fmt)+1);
}
void printf(fmt,data)
char *fmt;
int data;
void printf(const char *fmt, ...)
{
char buf[120],*p;
p = buf;
do_printf(buf,fmt,&data);
do_printf(buf, fmt, ((const int *)&fmt)+1);
while (*p) putchar(*p++);
}
#ifdef IMAGE_MENU
/**************************************************************************
INET_NTOA - Convert an ascii x.x.x.x to binary form
INET_ATON - Convert an ascii x.x.x.x to binary form
**************************************************************************/
int inet_ntoa(p, i)
char *p;
in_addr *i;
int inet_aton(char *p, in_addr *i)
{
unsigned long ip = 0;
int val;
@ -195,10 +186,9 @@ int inet_ntoa(p, i)
}
#endif /* IMAGE_MENU */
#endif /* 0 */
#endif /* ! GRUB */
int getdec(ptr)
char **ptr;
int getdec(char **ptr)
{
char *p = *ptr;
int ret=0;
@ -211,31 +201,33 @@ int getdec(ptr)
return(ret);
}
#if 0
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
#define K_STATUS 0x64 /* keyboard status */
#define K_CMD 0x64 /* keybd ctlr command (write-only) */
#ifndef GRUB
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
#define K_STATUS 0x64 /* keyboard status */
#define K_CMD 0x64 /* keybd ctlr command (write-only) */
#define K_OBUF_FUL 0x01 /* output buffer full */
#define K_IBUF_FUL 0x02 /* input buffer full */
#define K_OBUF_FUL 0x01 /* output buffer full */
#define K_IBUF_FUL 0x02 /* input buffer full */
#define KC_CMD_WIN 0xd0 /* read output port */
#define KC_CMD_WOUT 0xd1 /* write output port */
#define KB_A20 0xdf /* enable A20,
#define KB_SET_A20 0xdf /* enable A20,
enable output buffer full interrupt
enable data line
disable clock line */
#define KB_UNSET_A20 0xdd /* enable A20,
enable output buffer full interrupt
enable data line
disable clock line */
#ifndef IBM_L40
static void empty_8042(void)
{
extern void slowdownio();
unsigned long time;
char st;
slowdownio();
slowdownio();
time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */
while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
(st & K_IBUF_FUL)) &&
currticks() < time)
inb(K_RDWR);
@ -245,99 +237,105 @@ static void empty_8042(void)
/*
* Gate A20 for high memory
*/
void gateA20()
void gateA20_set(void)
{
#ifdef IBM_L40
outb(0x2, 0x92);
#else IBM_L40
#else /* IBM_L40 */
empty_8042();
outb(KC_CMD_WOUT, K_CMD);
empty_8042();
outb(KB_A20, K_RDWR);
outb(KB_SET_A20, K_RDWR);
empty_8042();
#endif IBM_L40
#endif /* IBM_L40 */
}
#ifdef TAGGED_IMAGE
/*
* Unset Gate A20 for high memory - some operating systems (mainly old 16 bit
* ones) don't expect it to be set by the boot loader.
*/
void gateA20_unset(void)
{
#ifdef IBM_L40
outb(0x0, 0x92);
#else /* IBM_L40 */
empty_8042();
outb(KC_CMD_WOUT, K_CMD);
empty_8042();
outb(KB_UNSET_A20, K_RDWR);
empty_8042();
#endif /* IBM_L40 */
}
#endif
#ifdef ETHERBOOT32
/* Serial console is only implemented in ETHERBOOT32 for now */
void
putchar(int c)
{
#ifdef ANSIESC
handleansi(c);
return;
#endif
#ifndef ANSIESC
if (c == '\n')
putchar('\r');
#ifdef SERIAL_CONSOLE
#if SERIAL_CONSOLE == DUAL
putc(c);
#endif /* SERIAL_CONSOLE == DUAL */
serial_putc(c);
#endif
#ifdef CONSOLE_CRT
#ifdef ANSIESC
handleansi(c);
#else
putc(c);
#endif /* SERIAL_CONSOLE */
#endif
#endif
#ifdef CONSOLE_SERIAL
#ifdef ANSIESC
if (c == '\n')
serial_putc('\r');
#endif
serial_putc(c);
#endif
}
/**************************************************************************
GETCHAR - Read the next character from the console WITHOUT ECHO
**************************************************************************/
int
getchar(int in_buf)
getchar(void)
{
int c=256;
int c = 256;
loop:
#ifdef SERIAL_CONSOLE
#if SERIAL_CONSOLE == DUAL
if (ischar())
c = getc();
do {
#ifdef CONSOLE_CRT
if (ischar())
c = getc();
#endif
if (serial_ischar())
c = serial_getc();
#else
if (ischar())
c = getc();
#ifdef CONSOLE_SERIAL
if (serial_ischar())
c = serial_getc();
#endif
if (c==256){
goto loop;
}
} while (c==256);
if (c == '\r')
c = '\n';
if (c == '\b') {
if (in_buf != 0) {
putchar('\b');
putchar(' ');
} else {
goto loop;
}
}
putchar(c);
return(c);
return c;
}
int
iskey(void)
{
int isc;
/*
* Checking the keyboard has the side effect of enabling clock
* interrupts so that bios_tick works. Check the keyboard to
* get this side effect even if we only want the serial status.
*/
#ifdef SERIAL_CONSOLE
#if SERIAL_CONSOLE == DUAL
#ifdef CONSOLE_CRT
if (ischar())
return 1;
#endif
#ifdef CONSOLE_SERIAL
if (serial_ischar())
return 1;
#else
if (ischar())
return 1;
#endif
return 0;
}
#endif /* ETHERBOOT32 */
#endif
#endif /* ! GRUB */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/

View file

@ -1,15 +0,0 @@
/*
* This program is free software; you can redistribute 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.
*/
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);

View file

@ -1,195 +0,0 @@
/*
* 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 */

View file

@ -1,10 +1,13 @@
/*
/*
* This program is free software; you can redistribute 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.
*/
#ifndef NIC_H
#define NIC_H
/*
* Structure returned from eth_probe and passed to other driver
* functions.
@ -14,12 +17,14 @@ 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 (*transmit)P((struct nic *, const char *d,
unsigned int t, unsigned int s, const char *p));
void (*disable)P((struct nic *));
char aui;
char *node_addr;
unsigned char *node_addr;
char *packet;
int packetlen;
unsigned int packetlen;
void *priv_data; /* driver can hang private data here */
};
#endif /* NIC_H */

View file

@ -1,4 +1,3 @@
/**************************************************************************
ETHERBOOT - BOOTP/TFTP Bootstrap Program
@ -25,6 +24,10 @@ RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99
#include "etherboot.h"
#include "nic.h"
#include "ns8390.h"
#ifdef INCLUDE_NS8390
#include "pci.h"
#endif
#include "cards.h"
static unsigned char eth_vendor, eth_flags, eth_laar;
static unsigned short eth_nic_base, eth_asic_base;
@ -32,9 +35,9 @@ static unsigned char eth_memsize, eth_rx_start, eth_tx_start;
static Address eth_bmem, eth_rmem;
static unsigned char eth_drain_receiver;
#ifdef INCLUDE_WD
#ifdef INCLUDE_WD
static struct wd_board {
char *name;
const char *name;
char id;
char flags;
char memsize;
@ -54,7 +57,7 @@ static struct wd_board {
{"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}
{NULL, 0, 0, 0}
};
#endif
@ -64,48 +67,45 @@ static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */
#if defined(INCLUDE_WD)
#define eth_probe wd_probe
#if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NEPCI)
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE[PCI]
#if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
#endif
#endif
#if defined(INCLUDE_3C503)
#define eth_probe t503_probe
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI) || defined(INCLUDE_WD)
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE[PCI]
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
#endif
#endif
#if defined(INCLUDE_NE)
#define eth_probe ne_probe
#if defined(INCLUDE_NEPCI) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE[PCI]
#if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
#endif
#endif
#if defined(INCLUDE_NEPCI)
#if defined(INCLUDE_NS8390)
#define eth_probe nepci_probe
#if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE[PCI]
Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390
#endif
#endif
#if defined(INCLUDE_3C503)
#define ASIC_PIO _3COM_RFMSB
#else
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI)
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
#define ASIC_PIO NE_DATA
#endif
#endif
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))
/**************************************************************************
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;
static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
{
if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }
outb(D8390_COMMAND_RD2 |
@ -122,17 +122,17 @@ static void eth_pio_read(src, dst, cnt)
outb(src >> 8, eth_asic_base + _3COM_DAMSB);
outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);
#endif
if (eth_flags & FLAG_16BIT)
cnt >>= 1;
cnt >>= 1;
while(cnt--) {
#ifdef INCLUDE_3C503
while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
;
while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
;
#endif
if (eth_flags & FLAG_16BIT) {
if (eth_flags & FLAG_16BIT) {
*((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO);
dst += 2;
}
@ -148,10 +148,7 @@ static void eth_pio_read(src, dst, cnt)
/**************************************************************************
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;
static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt)
{
#ifdef COMPEX_RL2000_FIX
unsigned int x;
@ -166,7 +163,7 @@ static void eth_pio_write(src, dst, cnt)
outb(dst>>8, eth_nic_base + D8390_P0_RSAR1);
outb(D8390_COMMAND_RD1 |
D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);
#ifdef INCLUDE_3C503
outb(dst & 0xff, eth_asic_base + _3COM_DALSB);
outb(dst >> 8, eth_asic_base + _3COM_DAMSB);
@ -175,21 +172,21 @@ static void eth_pio_write(src, dst, cnt)
#endif
if (eth_flags & FLAG_16BIT)
cnt >>= 1;
cnt >>= 1;
while(cnt--)
{
#ifdef INCLUDE_3C503
while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
;
while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0)
;
#endif
if (eth_flags & FLAG_16BIT) {
if (eth_flags & FLAG_16BIT) {
outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO);
src += 2;
}
else
outb(*(src++), eth_asic_base + ASIC_PIO);
outb(*(src++), eth_asic_base + ASIC_PIO);
}
#ifdef INCLUDE_3C503
@ -216,9 +213,9 @@ static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt)
#endif
/**************************************************************************
ETH_RESET - Reset adapter
NS8390_RESET - Reset adapter
**************************************************************************/
static void eth_reset(struct nic *nic)
static void ns8390_reset(struct nic *nic)
{
int i;
@ -272,19 +269,19 @@ static void eth_reset(struct nic *nic)
outb(0, eth_nic_base+D8390_P0_TCR);
outb(4, eth_nic_base+D8390_P0_RCR); /* allow broadcast frames */
#ifdef INCLUDE_3C503
#ifdef INCLUDE_3C503
/*
* 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.
*/
t503_output = (nic->aui) ? 0 : _3COM_CR_XSEL;
outb(t503_output, eth_asic_base + _3COM_CR);
t503_output = (nic->aui) ? 0 : _3COM_CR_XSEL;
outb(t503_output, eth_asic_base + _3COM_CR);
#endif
}
static int eth_poll(struct nic *nic);
static int ns8390_poll(struct nic *nic);
#ifndef INCLUDE_3C503
/**************************************************************************
@ -327,7 +324,7 @@ static void eth_rx_overrun(struct nic *nic)
/* clear the RX ring, acknowledge overrun interrupt */
eth_drain_receiver = 1;
while (eth_poll(nic))
while (ns8390_poll(nic))
/* Nothing */;
eth_drain_receiver = 0;
outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);
@ -338,18 +335,18 @@ static void eth_rx_overrun(struct nic *nic)
#endif /* INCLUDE_3C503 */
/**************************************************************************
ETH_TRANSMIT - Transmit a frame
NS8390_TRANSMIT - Transmit a frame
**************************************************************************/
static void eth_transmit(
static void ns8390_transmit(
struct nic *nic,
char *d, /* Destination */
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
const char *p) /* Packet */
{
int c; /* used in ETHERBOOT16 */
#ifdef INCLUDE_3C503
#ifdef INCLUDE_3C503
if (!(eth_flags & FLAG_PIO)) {
#ifdef ETHERBOOT32
memcpy((void *)eth_bmem, d, ETHER_ADDR_SIZE); /* dst */
@ -374,8 +371,8 @@ static void eth_transmit(
#endif
}
#endif
#ifdef INCLUDE_WD
#ifdef INCLUDE_WD
/* Memory interface */
if (eth_flags & FLAG_16BIT) {
outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);
@ -421,8 +418,8 @@ static void eth_transmit(
#if defined(INCLUDE_3C503)
if (eth_flags & FLAG_PIO) {
#endif
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))
/* Programmed I/O */
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))
/* Programmed I/O */
unsigned short type;
type = (t >> 8) | (t << 8);
eth_pio_write(d, eth_tx_start<<8, ETHER_ADDR_SIZE);
@ -460,9 +457,9 @@ static void eth_transmit(
}
/**************************************************************************
ETH_POLL - Wait for a frame
NS8390_POLL - Wait for a frame
**************************************************************************/
static int eth_poll(struct nic *nic)
static int ns8390_poll(struct nic *nic)
{
int ret = 0;
unsigned char rstat, curr, next;
@ -564,16 +561,21 @@ static int eth_poll(struct nic *nic)
}
/**************************************************************************
ETH_DISABLE - Turn off adapter
NS8390_DISABLE - Turn off adapter
**************************************************************************/
static void eth_disable(struct nic *nic)
static void ns8390_disable(struct nic *nic)
{
}
/**************************************************************************
ETH_PROBE - Look for an adapter
**************************************************************************/
#ifdef INCLUDE_NS8390
struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs,
struct pci_device *pci)
#else
struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
#endif
{
int i;
struct wd_board *brd;
@ -585,7 +587,7 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
eth_vendor = VENDOR_NONE;
eth_drain_receiver = 0;
#ifdef INCLUDE_WD
#ifdef INCLUDE_WD
/******************************************************************
Search for WD/SMC cards
******************************************************************/
@ -709,7 +711,7 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
}
putchar('\n');
#endif
#ifdef INCLUDE_3C503
#ifdef INCLUDE_3C503
/******************************************************************
Search for 3Com 3c503 if no WD/SMC cards
******************************************************************/
@ -780,7 +782,7 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
eth_vendor = VENDOR_3COM;
/* Need this to make eth_poll() happy. */
/* Need this to make ns8390_poll() happy. */
eth_rmem = eth_bmem - 0x2000;
@ -794,9 +796,9 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
printf("\n3Com 3c503 base 0x%x, ", eth_nic_base);
if (eth_flags & FLAG_PIO)
printf("PIO mode");
printf("PIO mode");
else
printf("memory 0x%X", eth_bmem);
printf("memory 0x%X", eth_bmem);
printf(", %s, addr ", nic->aui ? "AUI" : "internal xcvr");
for (i=0; i<ETHER_ADDR_SIZE; i++) {
printf("%b",(int)(nic->node_addr[i] =
@ -818,23 +820,23 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
* Clear memory and verify that it worked (we use only 8K)
*/
if (!(eth_flags & FLAG_PIO)) {
if (!(eth_flags & FLAG_PIO)) {
#ifdef ETHERBOOT32
memset((char *)eth_bmem, 0, 0x2000);
for(i = 0; i < 0x2000; ++i)
if (*(((char *)eth_bmem)+i)) {
printf ("Failed to clear 3c503 shared mem.\n");
return (0);
}
memset((char *)eth_bmem, 0, 0x2000);
for(i = 0; i < 0x2000; ++i)
if (*(((char *)eth_bmem)+i)) {
printf ("Failed to clear 3c503 shared mem.\n");
return (0);
}
#endif
#ifdef ETHERBOOT16
bzerof(eth_bmem, 0x2000);
bzerof(eth_bmem, 0x2000);
if (!fbsame(eth_bmem, 0, 0x2000)) {
printf ("Failed to clear 3c503 shared mem.\n");
return (0);
}
#endif
}
}
/*
* Initialize GA page/start/stop registers.
*/
@ -845,14 +847,14 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
}
#endif
#if defined(INCLUDE_NE) || defined(INCLUDE_NEPCI)
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
/******************************************************************
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";
static char test[] = "NE*000 memory";
static unsigned short base[] = {
#ifdef NE_SCAN
NE_SCAN,
@ -877,6 +879,10 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
outb(D8390_DCR_FT1 | D8390_DCR_LS, eth_nic_base + D8390_P0_DCR);
outb(MEM_8192, eth_nic_base + D8390_P0_PSTART);
outb(MEM_16384, eth_nic_base + D8390_P0_PSTOP);
#ifdef INCLUDE_NS8390
eth_flags |= FLAG_16BIT; /* force 16-bit mode */
#endif
eth_pio_write(test, 8192, sizeof(test));
eth_pio_read(8192, testbuf, sizeof(test));
if (!memcmp(test, testbuf, sizeof(test)))
@ -914,11 +920,11 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
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;
ns8390_reset(nic);
nic->reset = ns8390_reset;
nic->poll = ns8390_poll;
nic->transmit = ns8390_transmit;
nic->disable = ns8390_disable;
return(nic);
}

View file

@ -17,7 +17,7 @@ Western Digital/SMC Board Definitions
**************************************************************************/
#define WD_LOW_BASE 0x200
#define WD_HIGH_BASE 0x3e0
#ifndef WD_DEFAULT_MEM
#ifndef WD_DEFAULT_MEM
#define WD_DEFAULT_MEM 0xD0000
#endif
#define WD_NIC_ADDR 0x10
@ -67,7 +67,7 @@ Western Digital/SMC Board Types
3com 3c503 definitions
**************************************************************************/
#ifndef _3COM_BASE
#ifndef _3COM_BASE
#define _3COM_BASE 0x300
#endif

View file

@ -1,601 +0,0 @@
/*
Tulip and clone Etherboot Driver
By Marty Connor (mdc@thinguin.org)
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
Based on Ken Yap's Tulip Etherboot Driver and Donald Becker's
Linux Tulip Driver. Supports N-Way speed auto-configuration on
MX98715, MX98715A and MX98725. Support inexpensive PCI 10/100 cards
based on the Macronix MX987x5 chip, such as the SOHOware Fast
model SFA110A, and the LinkSYS model LNE100TX. The NetGear
model FA310X, based on the LC82C168 chip is also supported.
Documentation and source code used:
Source for Etherboot driver at
http://www.slug.org.au/etherboot/
MX98715A Data Sheet and MX98715A Application Note
on http://www.macronix.com/ (PDF format files)
Source for Linux tulip driver at
http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
Adapted by Ken Yap from
FreeBSD netboot DEC 21143 driver
Author: David Sharp
date: Nov/98
Some code fragments were taken from verious places, Ken Yap's
etherboot, FreeBSD's if_de.c, and various Linux related files.
DEC's manuals for the 21143 and SROM format were very helpful.
The Linux de driver development page has a number of links to
useful related information. Have a look at:
ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html
*/
/*********************************************************************/
/* Revision History */
/*********************************************************************/
/*
11 Jan 2000 mdc 0.75b4
Added support for NetGear FA310TX card based on the LC82C168
chip. This should also support Lite-On LC82C168 boards.
Added simple MII support. Re-arranged code to better modularize
initializations.
04 Dec 1999 mdc 0.75b3
Added preliminary support for LNE100TX PCI cards. Should work for
PNIC2 cards. No MII support, but single interface (RJ45) tulip
cards seem to not care.
03 Dec 1999 mdc 0.75b2
Renamed from mx987x5 to ntulip, merged in original tulip init code
from tulip.c to support other tulip compatible cards.
02 Dec 1999 mdc 0.75b1
Released Beta MX987x5 Driver for code review and testing to netboot
and thinguin mailing lists.
*/
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
/*********************************************************************/
/* Declarations */
/*********************************************************************/
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
/* Register offsets for tulip device */
enum ntulip_offsets {
CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
};
#define DEC_21142_CSR6_TTM 0x00400000 /* Transmit Threshold Mode */
#define DEC_21142_CSR6_HBD 0x00080000 /* Heartbeat Disable */
#define DEC_21142_CSR6_PS 0x00040000 /* Port Select */
/* EEPROM Address width definitions */
#define EEPROM_ADDRLEN 6
#define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */
/* Data Read from the EEPROM */
static unsigned char ee_data[EEPROM_SIZE];
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << addr_len)
#define EE_READ_CMD (6 << addr_len)
#define EE_ERASE_CMD (7 << addr_len)
/* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
#define EE_CS 0x01 /* 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. Even at 33Mhz current PCI
implementations don't overrun the EEPROM clock. We add a bus
turn-around to insure that this remains true. */
#define eeprom_delay() inl(ee_addr)
/* helpful macro if on a big_endian machine for changing byte order.
not strictly needed on Intel */
#define le16_to_cpu(val) (val)
/* Calibration constant for udelay loop. Very approximate */
#define UADJUST 870
/* transmit and receive descriptor format */
struct txrxdesc {
unsigned long status; /* owner, status */
unsigned long buf1sz:11, /* size of buffer 1 */
buf2sz:11, /* size of buffer 2 */
control:10; /* control bits */
unsigned char *buf1addr; /* buffer 1 address */
unsigned char *buf2addr; /* buffer 2 address */
};
/* Size of transmit and receive buffers */
#define BUFLEN 1600
/* Note: transmit and receive buffers must be longword aligned and
longword divisable */
/* transmit descriptor and buffer */
static struct txrxdesc txd;
static unsigned char txb[BUFLEN];
/* receive descriptor(s) and buffer(s) */
#define NRXD 4
static struct txrxdesc rxd[NRXD];
static int rxd_tail = 0;
static unsigned char rxb[NRXD][BUFLEN];
/* PCI Bus parameters */
static unsigned short vendor, dev_id;
static unsigned long ioaddr;
static unsigned long devfn;
/* buffer for ethernet header */
static unsigned char ehdr[ETHER_HDR_SIZE];
/* MIIs found */
static int mii_cnt;
/* Temporary CSR6 storage */
static int csr6;
/*********************************************************************/
/* Utility Routines */
/*********************************************************************/
#undef NTULIP_DEBUG
#undef NTULIP_DEBUG_WHERE
static void inline whereami (char *str)
{
#ifdef NTULIP_DEBUG_WHERE
printf("%s\n", str);
// sleep(2);
#endif
}
/*********************************************************************/
/* Delay Code */
/*********************************************************************/
/* Assumes 33MHz PCI bus. This is not very accurate and should be used
only with gross over estimations of required delay times unless
UADJUST is tuned to your specific processor and I/O subsystem. */
static void udelay(unsigned long usec)
{
unsigned long i;
for (i=((usec*UADJUST)/33)+1; i>0; i--)
(void) inl(ioaddr + CSR0);
}
/*********************************************************************/
/* Media Descriptor Code */
/*********************************************************************/
static int lc82c168_mdio_read(int phy_id, int location)
{
int i = 1000;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int retval = 0;
whereami("mdio_read\n");
outl(0x60020000 | (phy_id<<23) | (location<<18), ioaddr + 0xA0);
inl(ioaddr + 0xA0);
inl(ioaddr + 0xA0);
while (--i > 0)
if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
return retval & 0xffff;
if (i == 0) printf("mdio read timeout!\n");
return 0xffff;
}
static void lc82c168_mdio_write(int phy_id, int location, int value)
{
int i = 1000;
int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
whereami("mdio_write\n");
outl(cmd, ioaddr + 0xA0);
do
if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
break;
while (--i > 0);
if (i == 0) printf("mdio write timeout!\n");
return;
}
static void lc82c168_do_mii()
{
int phy, phy_idx;
whereami("do_mii\n");
mii_cnt = 0;
for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < 4; phy++) {
int mii_status = lc82c168_mdio_read(phy, 1);
if ((mii_status & 0x8301) == 0x8001 ||
((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) {
int mii_reg0 = lc82c168_mdio_read(phy, 0);
int mii_advert = lc82c168_mdio_read(phy, 4);
int mii_reg4 = ((mii_status >> 6) & 0x01E1) | 1;
phy_idx++;
printf("%s: MII trcvr #%d "
"config %x status %x advertising %x reg4 %x.\n",
"LC82C168", phy, mii_reg0, mii_status, mii_advert, mii_reg4);
lc82c168_mdio_write(phy, 0, mii_reg0 | 0x1000);
if (mii_advert != mii_reg4)
lc82c168_mdio_write(phy, 4, mii_reg4);
}
}
mii_cnt = phy_idx;
#ifdef NTULIP_DEBUG
printf("mii_cnt = %d\n", mii_cnt);
#endif
}
/*********************************************************************/
/* EEPROM Reading Code */
/*********************************************************************/
/* EEPROM routines adapted from the Linux Tulip Code */
/* Reading a serial EEPROM is a "bit" grungy, but we work our way
through:->.
*/
static int read_eeprom(unsigned long ioaddr, int location, int addr_len)
{
int i;
unsigned short retval = 0;
long ee_addr = ioaddr + CSR9;
int read_cmd = location | EE_READ_CMD;
whereami("read_eeprom\n");
outl(EE_ENB & ~EE_CS, ee_addr);
outl(EE_ENB, ee_addr);
/* Shift the read command bits out. */
for (i = 4 + addr_len; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
outl(EE_ENB | dataval, ee_addr);
eeprom_delay();
outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay();
}
outl(EE_ENB, ee_addr);
for (i = 16; i > 0; i--) {
outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay();
retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
outl(EE_ENB, ee_addr);
eeprom_delay();
}
/* Terminate the EEPROM access. */
outl(EE_ENB & ~EE_CS, ee_addr);
return retval;
}
/*********************************************************************/
/* ntulip_init_ring - setup the tx and rx descriptors */
/*********************************************************************/
static void ntulip_init_ring(struct nic *nic)
{
int i;
/* setup the transmit descriptor */
memset(&txd, 0, sizeof(struct txrxdesc));
txd.buf1addr = &txb[0];
txd.buf2addr = &txb[0]; /* just in case */
txd.buf1sz = 192; /* setup packet must be 192 bytes */
txd.buf2sz = 0;
txd.control = 0x020; /* setup packet */
txd.status = 0x80000000; /* give ownership to device */
/* construct perfect filter frame with mac address as first match
and broadcast address for all others */
for (i=0; i<192; i++) txb[i] = 0xff;
txb[0] = nic->node_addr[0];
txb[1] = nic->node_addr[1];
txb[4] = nic->node_addr[2];
txb[5] = nic->node_addr[3];
txb[8] = nic->node_addr[4];
txb[9] = nic->node_addr[5];
/* setup receive descriptor */
for (i=0; i<NRXD; i++) {
memset(&rxd[i], 0, sizeof(struct txrxdesc));
rxd[i].buf1addr = &rxb[i][0];
rxd[i].buf2addr = 0; /* not used */
rxd[i].buf1sz = BUFLEN;
rxd[i].buf2sz = 0; /* not used */
rxd[i].control = 0x0;
rxd[i].status = 0x80000000; /* give ownership it to device */
}
/* Set Receive end of ring on last descriptor */
rxd[NRXD - 1].control = 0x008;
rxd_tail = 0;
}
/*********************************************************************/
/* eth_reset - Reset adapter */
/*********************************************************************/
static void ntulip_reset(struct nic *nic)
{
whereami("ntulip_reset\n");
if (vendor == PCI_VENDOR_ID_MACRONIX && dev_id == PCI_DEVICE_ID_MX987x5) {
/* set up 10-BASE-T Control Port */
outl(0xFFFFFFFF, ioaddr + CSR14);
/* set up 10-BASE-T Status Port */
outl(0x00001000, ioaddr + CSR12);
/* Set Operation Control Register (CSR6) for MX987x5
to allow N-Way Active Speed selection, and
start the chip's Tx to process setup frame.
While it is possible to force speed selection,
this is probably more useful most of the time.
*/
outl(0x01A80200, ioaddr + CSR6);
} else if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_LC82C115) {
/* This is MX987x5 init code. It seems to work for the LNE100TX
but should be replaced when we figure out the right way
to do this initialization
*/
outl(0xFFFFFFFF, ioaddr + CSR14);
outl(0x00001000, ioaddr + CSR12);
outl(0x01A80200, ioaddr + CSR6);
} else if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_DEC_TULIP) {
lc82c168_do_mii();
} else {
/* Set to 10Mbps half-duplex */
outl(0x00000000, ioaddr + CSR13);
outl(0x7F3F0000, ioaddr + CSR14);
outl(0x08000008, ioaddr + CSR15);
outl(0x00000000, ioaddr + CSR13);
outl(0x00000001, ioaddr + CSR13);
outl(0x02404000, ioaddr + CSR6);
outl(0x08AF0008, ioaddr + CSR15);
outl(0x00050008, ioaddr + CSR15);
}
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
outl(0x00000001, ioaddr + CSR0);
udelay(50000);
udelay(50000);
/* turn off reset and set cache align=16lword, burst=unlimit */
outl(0x01A08000, ioaddr + CSR0);
/* set up transmit and receive descriptors */
ntulip_init_ring(nic);
/* Point to receive descriptor */
outl((unsigned long)&rxd[0], ioaddr + CSR3);
outl((unsigned long)&txd , ioaddr + CSR4);
csr6 = 0x02404000;
/* Chip specific init code */
if (vendor == PCI_VENDOR_ID_MACRONIX && dev_id == PCI_DEVICE_ID_MX987x5) {
csr6 = 0x01880200;
/* Set CSR16 and CSR20 to values that allow device modification */
outl(0x0B3C0000 | inl(ioaddr + CSR16), ioaddr + CSR16);
outl(0x00011000 | inl(ioaddr + CSR20), ioaddr + CSR20);
} else if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_LC82C115) {
/* This is MX987x5 init code. It seems to work for the LNE100TX
but should be replaced when we figure out the right way
to do this initialization.
*/
csr6 = 0x01880200;
outl(0x0B3C0000 | inl(ioaddr + CSR16), ioaddr + CSR16);
outl(0x00011000 | inl(ioaddr + CSR20), ioaddr + CSR20);
} else if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_DEC_TULIP) {
csr6 = 0x814C0000;
outl(0x00000001, ioaddr + CSR15);
} else if (vendor == PCI_VENDOR_ID_DEC && dev_id == PCI_DEVICE_ID_DEC_21142) {
/* check SROM for evidence of an MII interface */
/* get Controller_0 Info Leaf Offset from SROM - assume already in ee_data */
int offset = ee_data [27] + (ee_data [28] << 8);
/* check offset range and if we have an extended type 3 Info Block */
if ((offset >= 30) && (offset < 120) && (ee_data [offset + 3] > 128) &&
(ee_data [offset + 4] == 3)) {
/* must have an MII interface - disable heartbeat, select port etc. */
csr6 |= (DEC_21142_CSR6_HBD | DEC_21142_CSR6_PS);
csr6 &= ~(DEC_21142_CSR6_TTM);
}
}
/* Start the chip's Tx to process setup frame. */
outl(csr6, ioaddr + CSR6);
outl(csr6 | 0x00002000, ioaddr + CSR6);
outl(csr6 | 0x00002002, ioaddr + CSR6);
}
/*********************************************************************/
/* eth_transmit - Transmit a frame */
/*********************************************************************/
static void ntulip_transmit(struct nic *nic, char *d, unsigned int t,
unsigned int s, char *p)
{
unsigned int len;
int pad;
int status;
unsigned char c;
whereami("ntulip_transmit\n");
/* Stop Tx */
outl(inl(ioaddr + CSR6) & ~0x00002000, ioaddr + CSR6);
/* setup ethernet header */
memcpy(ehdr, d, ETHER_ADDR_SIZE);
memcpy(&ehdr[ETHER_ADDR_SIZE], nic->node_addr, ETHER_ADDR_SIZE);
ehdr[ETHER_ADDR_SIZE*2] = (t >> 8) & 0xff;
ehdr[ETHER_ADDR_SIZE*2+1] = t & 0xff;
/* setup the transmit descriptor */
memset(&txd, 0, sizeof(struct txrxdesc));
txd.buf1addr = &ehdr[0]; /* ethernet header */
txd.buf1sz = ETHER_HDR_SIZE;
txd.buf2addr = p; /* packet to transmit */
txd.buf2sz = s;
txd.control = 0x00000188; /* LS+FS+TER */
txd.status = 0x80000000; /* give it the device */
/* Point to transmit descriptor */
outl((unsigned long)&txd, ioaddr + CSR4);
/* Start Tx */
outl(inl(ioaddr + CSR6) | 0x00002000, ioaddr + CSR6);
udelay(300);
}
/*********************************************************************/
/* eth_poll - Wait for a frame */
/*********************************************************************/
static int ntulip_poll(struct nic *nic)
{
int x;
whereami("ntulip_poll\n");
if (rxd[rxd_tail].status & 0x80000000)
return 0;
whereami("ntulip_poll got one\n");
nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16;
/* copy packet to working buffer */
/* XXX - this copy could be avoided with a little more work
but for now we are content with it because the optimised
memcpy is quite fast */
memcpy(nic->packet, &rxb[rxd_tail][0], nic->packetlen);
/* return the descriptor and buffer to receive ring */
rxd[rxd_tail].status = 0x80000000;
rxd_tail++;
if (rxd_tail == NRXD) rxd_tail = 0;
return 1;
}
/*********************************************************************/
/* eth_disable - Disable the interface */
/*********************************************************************/
static void ntulip_disable(struct nic *nic)
{
whereami("ntulip_disable\n");
/* disable interrupts */
outl(0x00000000, ioaddr + CSR7);
/* Stop the chip's Tx and Rx processes. */
outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
/* Clear the missed-packet counter. */
(volatile unsigned long)inl(ioaddr + CSR8);
}
/*********************************************************************/
/* eth_probe - Look for an adapter */
/*********************************************************************/
struct nic *ntulip_probe(struct nic *nic, unsigned short *io_addrs,
struct pci_device *pci)
{
int i;
whereami("ntulip_probe\n");
if (io_addrs == 0 || *io_addrs == 0)
return 0;
vendor = pci->vendor;
dev_id = pci->dev_id;
ioaddr = *io_addrs;
/* wakeup chip */
pcibios_write_config_dword(0, pci->devfn, 0x40, 0x00000000);
/* Stop the chip's Tx and Rx processes. */
outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
/* Clear the missed-packet counter. */
(volatile unsigned long)inl(ioaddr + CSR8);
/* Get MAC Address */
/* Hardware Address retrieval method for LC82C168 */
if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_DEC_TULIP) {
for (i = 0; i < 3; i++) {
int value, boguscnt = 100000;
outl(0x600 | i, ioaddr + 0x98);
do
value = inl(ioaddr + CSR9);
while (value < 0 && --boguscnt > 0);
nic->node_addr[i*2] = (u8)((value >> 8) & 0xff);
nic->node_addr[i*2 + 1] = (u8)( value & 0xff);
}
} else {
/* read EEPROM data */
for (i = 0; i < sizeof(ee_data)/2; i++)
((unsigned short *)ee_data)[i] =
le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));
/* extract MAC address from EEPROM buffer */
for (i=0; i<6; i++)
nic->node_addr[i] = ee_data[20+i];
}
printf("NTulip %b:%b:%b:%b:%b:%b at ioaddr 0x%x\n",
nic->node_addr[0],nic->node_addr[1],nic->node_addr[2],nic->node_addr[3],
nic->node_addr[4],nic->node_addr[5],ioaddr);
/* initialize device */
ntulip_reset(nic);
nic->reset = ntulip_reset;
nic->poll = ntulip_poll;
nic->transmit = ntulip_transmit;
nic->disable = ntulip_disable;
return nic;
}

View file

@ -1,4 +1,4 @@
#ifndef __OSDEP_H__
#ifndef __OSDEP_H__
#define __OSDEP_H__
/*
@ -8,30 +8,39 @@
* your option) any later version.
*/
#if 1
# define ETHERBOOT32
# include <byteorder.h>
# if 0
# include <linux-asm-string.h>
# endif
# include <linux-asm-io.h>
#else
#ifdef __linux__
#if defined(__linux__) || defined(__FreeBSD__) || defined(GRUB)
#define ETHERBOOT32
#include <asm/byteorder.h>
#include "linux-asm-string.h"
#include "linux-asm-io.h"
#define _edata edata /* ELF does not prepend a _ */
#define _end end
#endif
#define ntohl(x) swap32(x)
#define htonl(x) swap32(x)
#define ntohs(x) swap16(x)
#define htons(x) swap16(x)
#ifdef __FreeBSD__
#define ETHERBOOT32
#include <sys/types.h>
#include "linux-asm-string.h"
static inline unsigned long int swap32(unsigned long int x)
{
__asm__("xchgb %b0,%h0\n\t"
"rorl $16,%0\n\t"
"xchgb %b0,%h0"
: "=q" (x)
: "0" (x));
return x;
}
static inline unsigned short int swap16(unsigned short int x)
{
__asm__("xchgb %b0,%h0"
: "=q" (x)
: "0" (x));
return x;
}
#ifndef GRUB
# include "linux-asm-string.h"
#endif /* ! GRUB */
#include "linux-asm-io.h"
#ifndef GRUB
#define _edata edata /* ELF does not prepend a _ */
#define _end end
#endif /* ! GRUB */
#endif
#ifdef __BCC__
@ -48,7 +57,6 @@ typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
#endif
#endif
#if !defined(ETHERBOOT16) && !defined(ETHERBOOT32)
Error, neither ETHERBOOT16 nor ETHERBOOT32 defined

376
netboot/otulip.c Normal file
View file

@ -0,0 +1,376 @@
/*
Etherboot DEC Tulip driver
adapted by Ken Yap from
FreeBSD netboot DEC 21143 driver
Author: David Sharp
date: Nov/98
Known to work on DEC DE500 using 21143-PC chipset.
Even on cards with the same chipset there can be
incompatablity problems with the way media selection
and status LED settings are done. See comments below.
Some code fragments were taken from verious places,
Ken Yap's etherboot, FreeBSD's if_de.c, and various
Linux related files. DEC's manuals for the 21143 and
SROM format were very helpful. The Linux de driver
development page has a number of links to useful
related information. Have a look at:
ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html
*/
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#include "cards.h"
#include "otulip.h"
static unsigned short vendor, dev_id;
static unsigned short ioaddr;
static unsigned int *membase;
static unsigned char srom[1024];
#define BUFLEN 1536 /* must be longword divisable */
/* buffers must be longword aligned */
/* transmit descriptor and buffer */
static struct txdesc txd;
/* receive descriptor(s) and buffer(s) */
#define NRXD 4
static struct rxdesc rxd[NRXD];
static int rxd_tail = 0;
#ifndef USE_INTERNAL_BUFFER
#define rxb ((char *)0x10000 - NRXD * BUFLEN)
#define txb ((char *)0x10000 - NRXD * BUFLEN - BUFLEN)
#else
static unsigned char rxb[NRXD * BUFLEN];
static unsigned char txb[BUFLEN];
#endif
static unsigned char ehdr[ETHER_HDR_SIZE]; /* buffer for ethernet header */
enum tulip_offsets {
CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78 };
/***************************************************************************/
/* 21143 specific stuff */
/***************************************************************************/
/* XXX assume 33MHz PCI bus, this is not very accurate and should be
used only with gross over estimations of required delay times unless
you tune UADJUST to your specific processor and I/O subsystem */
#define UADJUST 870
static void udelay(unsigned long usec) {
unsigned long i;
for (i=((usec*UADJUST)/33)+1; i>0; i--) (void) TULIP_CSR_READ(csr_0);
}
/* The following srom related code was taken from FreeBSD's if_de.c */
/* with minor alterations to make it work here. the Linux code is */
/* better but this was easier to use */
static void delay_300ns(void)
{
int idx;
for (idx = (300 / 33) + 1; idx > 0; idx--)
(void) TULIP_CSR_READ(csr_busmode);
}
#define EMIT do { TULIP_CSR_WRITE(csr_srom_mii, csr); delay_300ns(); } while (0)
static void srom_idle(void)
{
unsigned bit, csr;
csr = SROMSEL ; EMIT;
csr = SROMSEL | SROMRD; EMIT;
csr ^= SROMCS; EMIT;
csr ^= SROMCLKON; EMIT;
/*
* Write 25 cycles of 0 which will force the SROM to be idle.
*/
for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) {
csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
csr ^= SROMCLKON; EMIT; /* clock high; data valid */
}
csr ^= SROMCLKOFF; EMIT;
csr ^= SROMCS; EMIT;
csr = 0; EMIT;
}
static void srom_read(void)
{
unsigned idx;
const unsigned bitwidth = SROM_BITWIDTH;
const unsigned cmdmask = (SROMCMD_RD << bitwidth);
const unsigned msb = 1 << (bitwidth + 3 - 1);
unsigned lastidx = (1 << bitwidth) - 1;
srom_idle();
for (idx = 0; idx <= lastidx; idx++) {
unsigned lastbit, data, bits, bit, csr;
csr = SROMSEL ; EMIT;
csr = SROMSEL | SROMRD; EMIT;
csr ^= SROMCSON; EMIT;
csr ^= SROMCLKON; EMIT;
lastbit = 0;
for (bits = idx|cmdmask, bit = bitwidth + 3; bit > 0; bit--, bits <<= 1)
{
const unsigned thisbit = bits & msb;
csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
if (thisbit != lastbit) {
csr ^= SROMDOUT; EMIT; /* clock low; invert data */
} else {
EMIT;
}
csr ^= SROMCLKON; EMIT; /* clock high; data valid */
lastbit = thisbit;
}
csr ^= SROMCLKOFF; EMIT;
for (data = 0, bits = 0; bits < 16; bits++) {
data <<= 1;
csr ^= SROMCLKON; EMIT; /* clock high; data valid */
data |= TULIP_CSR_READ(csr_srom_mii) & SROMDIN ? 1 : 0;
csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
}
srom[idx*2] = data & 0xFF;
srom[idx*2+1] = data >> 8;
csr = SROMSEL | SROMRD; EMIT;
csr = 0; EMIT;
}
srom_idle();
}
/**************************************************************************
ETH_RESET - Reset adapter
***************************************************************************/
static void tulip_reset(struct nic *nic)
{
int x,cnt=2;
outl(0x00000001, ioaddr + CSR0);
udelay(1000);
/* turn off reset and set cache align=16lword, burst=unlimit */
outl(0x01A08000, ioaddr + CSR0);
/* for some reason the media selection does not take
the first time se it is repeated. */
while(cnt--) {
/* stop TX,RX processes */
if (cnt == 1)
outl(0x32404000, ioaddr + CSR6);
else
outl(0x32000040, ioaddr + CSR6);
/* XXX - media selection is vendor specific and hard coded right
here. This should be fixed to use the hints in the SROM and
allow media selection by the user at runtime. MII support
should also be added. Support for chips other than the
21143 should be added here as well */
/* start set to 10Mbps half-duplex */
/* setup SIA */
outl(0x0, ioaddr + CSR13); /* reset SIA */
outl(0x7f3f, ioaddr + CSR14);
outl(0x8000008, ioaddr + CSR15);
outl(0x0, ioaddr + CSR13);
outl(0x1, ioaddr + CSR13);
outl(0x2404000, ioaddr + CSR6);
/* initalize GP */
outl(0x8af0008, ioaddr + CSR15);
outl(0x50008, ioaddr + CSR15);
/* end set to 10Mbps half-duplex */
if (vendor == PCI_VENDOR_ID_MACRONIX && dev_id == PCI_DEVICE_ID_MX987x5) {
/* do stuff for MX98715 */
outl(0x01a80000, ioaddr + CSR6);
outl(0xFFFFFFFF, ioaddr + CSR14);
outl(0x00001000, ioaddr + CSR12);
}
outl(0x0, ioaddr + CSR7); /* disable interrupts */
/* construct setup packet which is used by the 21143 to
program its CAM to recognize interesting MAC addresses */
memset(&txd, 0, sizeof(struct txdesc));
txd.buf1addr = &txb[0];
txd.buf2addr = &txb[0]; /* just in case */
txd.buf1sz = 192; /* setup packet must be 192 bytes */
txd.buf2sz = 0;
txd.control = 0x020; /* setup packet */
txd.status = 0x80000000; /* give ownership to 21143 */
/* construct perfect filter frame */
/* with mac address as first match */
/* and broadcast address for all others */
for(x=0;x<192;x++) txb[x] = 0xff;
txb[0] = nic->node_addr[0];
txb[1] = nic->node_addr[1];
txb[4] = nic->node_addr[2];
txb[5] = nic->node_addr[3];
txb[8] = nic->node_addr[4];
txb[9] = nic->node_addr[5];
outl((unsigned long)&txd, ioaddr + CSR4); /* set xmit buf */
outl(0x2406000, ioaddr + CSR6); /* start transmiter */
udelay(50000); /* wait for the setup packet to be processed */
}
/* setup receive descriptor */
{
int x;
for(x=0;x<NRXD;x++) {
memset(&rxd[x], 0, sizeof(struct rxdesc));
rxd[x].buf1addr = &rxb[x * BUFLEN];
rxd[x].buf2addr = 0; /* not used */
rxd[x].buf1sz = BUFLEN;
rxd[x].buf2sz = 0; /* not used */
rxd[x].control = 0x0;
rxd[x].status = 0x80000000; /* give ownership it to 21143 */
}
rxd[NRXD - 1].control = 0x008; /* Set Receive end of ring on la
st descriptor */
rxd_tail = 0;
}
/* tell DC211XX where to find rx descriptor list */
outl((unsigned long)&rxd[0], ioaddr + CSR3);
/* start the receiver */
outl(0x2406002, ioaddr + CSR6);
}
/**************************************************************************
ETH_TRANSMIT - Transmit a frame
***************************************************************************/
static const char padmap[] = {
0, 3, 2, 1};
static void tulip_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
{
unsigned long time;
/* setup ethernet header */
memcpy(ehdr, d, ETHER_ADDR_SIZE);
memcpy(&ehdr[ETHER_ADDR_SIZE], nic->node_addr, ETHER_ADDR_SIZE);
ehdr[ETHER_ADDR_SIZE*2] = (t >> 8) & 0xff;
ehdr[ETHER_ADDR_SIZE*2+1] = t & 0xff;
/* setup the transmit descriptor */
memset(&txd, 0, sizeof(struct txdesc));
txd.buf1addr = &ehdr[0]; /* ethernet header */
txd.buf1sz = ETHER_HDR_SIZE;
txd.buf2addr = p; /* packet to transmit */
txd.buf2sz = s;
txd.control = 0x188; /* LS+FS+TER */
txd.status = 0x80000000; /* give it to 21143 */
outl(inl(ioaddr + CSR6) & ~0x00004000, ioaddr + CSR6);
outl((unsigned long)&txd, ioaddr + CSR4);
outl(inl(ioaddr + CSR6) | 0x00004000, ioaddr + CSR6);
/* Wait for transmit to complete before returning. not well tested.
time = currticks();
while(txd.status & 0x80000000) {
if (currticks() - time > 20) {
printf("transmit timeout.\n");
break;
}
}
*/
}
/**************************************************************************
ETH_POLL - Wait for a frame
***************************************************************************/
static int tulip_poll(struct nic *nic)
{
if (rxd[rxd_tail].status & 0x80000000) return 0;
nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16;
/* copy packet to working buffer */
/* XXX - this copy could be avoided with a little more work
but for now we are content with it because the optimised
memcpy(, , ) is quite fast */
memcpy(nic->packet, rxb + rxd_tail * BUFLEN, nic->packetlen);
/* return the descriptor and buffer to recieve ring */
rxd[rxd_tail].status = 0x80000000;
rxd_tail++;
if (rxd_tail == NRXD) rxd_tail = 0;
return 1;
}
static void tulip_disable(struct nic *nic)
{
/* nothing for the moment */
}
/**************************************************************************
ETH_PROBE - Look for an adapter
***************************************************************************/
struct nic *otulip_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci)
{
int i;
if (io_addrs == 0 || *io_addrs == 0)
return (0);
vendor = pci->vendor;
dev_id = pci->dev_id;
ioaddr = *io_addrs;
membase = (unsigned int *)pci->membase;
/* wakeup chip */
pcibios_write_config_dword(0,pci->devfn,0x40,0x00000000);
/* Stop the chip's Tx and Rx processes. */
/* outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6); */
/* Clear the missed-packet counter. */
/* (volatile int)inl(ioaddr + CSR8); */
srom_read();
for (i=0; i < 6; i++)
nic->node_addr[i] = srom[20+i];
printf("Tulip %b:%b:%b:%b:%b:%b at ioaddr 0x%x\n",
srom[20],srom[21],srom[22],srom[23],srom[24],srom[25],
ioaddr);
tulip_reset(nic);
nic->reset = tulip_reset;
nic->poll = tulip_poll;
nic->transmit = tulip_transmit;
nic->disable = tulip_disable;
return nic;
}

76
netboot/otulip.h Normal file
View file

@ -0,0 +1,76 @@
/* mostly stolen from FreeBSD if_de.c, if_devar.h */
#define TULIP_CSR_READ(csr) (membase[csr*2])
#define CSR_READ(csr) (membase[csr*2])
#define TULIP_CSR_WRITE(csr, val) (membase[csr*2] = val)
#define CSR_WRITE(csr, val) (membase[csr*2] = val)
#define csr_0 0
#define csr_1 1
#define csr_2 2
#define csr_3 3
#define csr_4 4
#define csr_5 5
#define csr_6 6
#define csr_7 7
#define csr_8 8
#define csr_9 9
#define csr_10 10
#define csr_11 11
#define csr_12 12
#define csr_13 13
#define csr_14 14
#define csr_15 15
#define csr_busmode csr_0
#define csr_txpoll csr_1
#define csr_rxpoll csr_2
#define csr_rxlist csr_3
#define csr_txlist csr_4
#define csr_status csr_5
#define csr_command csr_6
#define csr_intr csr_7
#define csr_missed_frames csr_8
#define csr_enetrom csr_9 /* 21040 */
#define csr_reserved csr_10 /* 21040 */
#define csr_full_duplex csr_11 /* 21040 */
#define csr_bootrom csr_10 /* 21041/21140A/?? */
#define csr_gp csr_12 /* 21140* */
#define csr_watchdog csr_15 /* 21140* */
#define csr_gp_timer csr_11 /* 21041/21140* */
#define csr_srom_mii csr_9 /* 21041/21140* */
#define csr_sia_status csr_12 /* 2104x */
#define csr_sia_connectivity csr_13 /* 2104x */
#define csr_sia_tx_rx csr_14 /* 2104x */
#define csr_sia_general csr_15 /* 2104x */
#define SROMSEL 0x0800
#define SROMCS 0x0001
#define SROMCLKON 0x0002
#define SROMCLKOFF 0x0002
#define SROMRD 0x4000
#define SROMWR 0x2000
#define SROM_BITWIDTH 6
#define SROMCMD_RD 6
#define SROMCSON 0x0001
#define SROMDOUT 0x0004
#define SROMDIN 0x0008
struct txdesc {
unsigned long status; /* owner, status */
unsigned long buf1sz:11, /* size of buffer 1 */
buf2sz:11, /* size of buffer 2 */
control:10; /* control bits */
const unsigned char *buf1addr; /* buffer 1 address */
const unsigned char *buf2addr; /* buffer 2 address */
};
struct rxdesc {
unsigned long status; /* owner, status */
unsigned long buf1sz:11, /* size of buffer 1 */
buf2sz:11, /* size of buffer 2 */
control:10; /* control bits */
unsigned char *buf1addr; /* buffer 1 address */
unsigned char *buf2addr; /* buffer 2 address */
};

View file

@ -9,9 +9,6 @@
** /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)
*/
/*
@ -27,7 +24,7 @@
/*#define DEBUG 1*/
static unsigned int pci_ioaddr = 0;
#ifdef CONFIG_PCI_DIRECT
#ifdef CONFIG_PCI_DIRECT
#define PCIBIOS_SUCCESSFUL 0x00
/*
@ -47,28 +44,28 @@ int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn,
int pcibios_read_config_word (unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned short *value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
*value = inw(0xCFC + (where&2));
return PCIBIOS_SUCCESSFUL;
return PCIBIOS_SUCCESSFUL;
}
static int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
static int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
unsigned char where, unsigned int *value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
*value = inl(0xCFC);
return PCIBIOS_SUCCESSFUL;
return PCIBIOS_SUCCESSFUL;
}
int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
unsigned char where, unsigned char value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
outb(value, 0xCFC + (where&3));
return PCIBIOS_SUCCESSFUL;
}
int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
unsigned char where, unsigned short value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
@ -85,7 +82,7 @@ int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, unsi
#undef CONFIG_CMD
#else /* CONFIG_PCI_DIRECT not defined */
#else /* CONFIG_PCI_DIRECT not defined */
static unsigned long bios32_entry = 0;
static struct {
@ -93,10 +90,10 @@ static struct {
unsigned short segment;
} bios32_indirect = { 0, KERN_CODE_SEG };
static long pcibios_entry = 0;
static struct {
unsigned long address;
unsigned short segment;
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)
@ -265,11 +262,11 @@ int pcibios_write_config_dword (unsigned char bus,
static void check_pcibios(void)
{
unsigned long signature;
unsigned long signature;
unsigned char present_status;
unsigned char major_revision;
unsigned char minor_revision;
unsigned long flags;
unsigned char minor_revision;
unsigned long flags;
int pack;
if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
@ -287,7 +284,7 @@ static void check_pcibios(void)
"D" (&pci_indirect)
: "bx", "cx");
restore_flags(flags);
present_status = (pack >> 16) & 0xff;
major_revision = (pack >> 8) & 0xff;
minor_revision = pack & 0xff;
@ -296,7 +293,7 @@ static void check_pcibios(void)
"BIOS????\n");
pcibios_entry = 0;
}
#if DEBUG
#if DEBUG
if (pcibios_entry) {
printf ("pcibios_init : PCI BIOS revision %b.%b"
" entry at 0x%X\n", major_revision,
@ -335,7 +332,7 @@ static void pcibios_init(void)
check->fields.revision, check);
continue;
}
#if DEBUG
#if DEBUG
printf("pcibios_init : BIOS32 Service Directory "
"structure at 0x%X\n", check);
#endif
@ -346,7 +343,7 @@ static void pcibios_init(void)
return;
} else {
bios32_entry = check->fields.entry;
#if DEBUG
#if DEBUG
printf("pcibios_init : BIOS32 Service Directory"
" entry at 0x%X\n", bios32_entry);
#endif
@ -357,7 +354,7 @@ static void pcibios_init(void)
if (bios32_entry)
check_pcibios();
}
#endif /* CONFIG_PCI_DIRECT not defined*/
#endif /* CONFIG_PCI_DIRECT not defined*/
static void scan_bus(struct pci_device *pcidev)
{
@ -391,10 +388,10 @@ static void scan_bus(struct pci_device *pcidev)
if (class == 0x06 && subclass == 0x04)
buses++;
#if DEBUG
#if DEBUG
printf("bus %x, function %x, vendor %x, device %x\n",
bus, devfn, vendor, device);
#endif
#endif
for (i = 0; pcidev[i].vendor != 0; i++) {
if (vendor != pcidev[i].vendor
|| device != pcidev[i].dev_id)
@ -415,11 +412,11 @@ static void scan_bus(struct pci_device *pcidev)
printf("Found %s at 0x%x, ROM address 0x%X\n",
pcidev[i].name, ioaddr, romaddr);
/* Take the first one or the one that matches in boot ROM address */
if (pci_ioaddr == 0 || romaddr == ((long) rom.rom_segment >> 4)) {
if (pci_ioaddr == 0 || romaddr == ((unsigned long) rom.rom_segment << 4)) {
pcidev[i].membase = membase;
pcidev[i].ioaddr = ioaddr;
pcidev[i].devfn = devfn;
return;
}
}
@ -430,7 +427,7 @@ static void scan_bus(struct pci_device *pcidev)
void eth_pci_init(struct pci_device *pcidev)
{
#ifndef CONFIG_PCI_DIRECT
#ifndef CONFIG_PCI_DIRECT
pcibios_init();
if (!pcibios_entry) {
printf("pci_init: no BIOS32 detected\n");

View file

@ -1,3 +1,6 @@
#ifndef PCI_H
#define PCI_H
/*
** Support for NE2000 PCI clones added David Monro June 1997
** Generalised for other PCI NICs by Ken Yap July 1997
@ -63,10 +66,10 @@
#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))
#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 {
@ -121,7 +124,7 @@ __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
#define PCI_DEVICE_ID_DEC_TULIP_PLUS 0x0014
#define PCI_DEVICE_ID_DEC_21142 0x0019
#define PCI_VENDOR_ID_SMC 0x10B8
#ifndef PCI_DEVICE_ID_SMC_EPIC100
#ifndef PCI_DEVICE_ID_SMC_EPIC100
# define PCI_DEVICE_ID_SMC_EPIC100 0x0005
#endif
#define PCI_VENDOR_ID_MACRONIX 0x10d9
@ -134,7 +137,7 @@ __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
struct pci_device {
unsigned short vendor, dev_id;
char *name;
const char *name;
unsigned int membase;
unsigned short ioaddr;
unsigned short devfn;
@ -148,3 +151,5 @@ extern int pcibios_read_config_word(unsigned char bus, unsigned char device_fn,
extern int pcibios_write_config_word (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short value);
extern int pcibios_write_config_dword(unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned int value);
#endif /* PCI_H */

View file

@ -56,14 +56,12 @@
*/
/* to get some global routines like printf */
#include "etherboot.h"
/* to get the interface to the body of the program */
#include "nic.h"
/* we have a PIC card */
#include "pci.h"
#include "cards.h"
#define RTL_TIMEOUT (1*TICKS_PER_SEC)
#define RTL_TIMEOUT (1*TICKS_PER_SEC)
/* PCI Tuning Parameters
Threshold is bytes transferred to chip before transmission starts. */
@ -153,7 +151,7 @@ enum rx_mode_bits {
};
static int ioaddr;
unsigned int cur_rx,cur_tx;
static unsigned int cur_rx,cur_tx;
/* The RTL8139 can only transmit from a contiguous, aligned memory block. */
static unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4)));
@ -163,18 +161,18 @@ static unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4)));
/* But we still give the user the choice of using an internal buffer
just in case - Ken */
#ifdef USE_INTERNAL_BUFFER
static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__ ((aligned(4)));
static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4)));
#else
static unsigned char *rx_ring = (unsigned char *)(0x10000 - (RX_BUF_LEN + 16));
#define rx_ring ((unsigned char *)(0x10000 - (RX_BUF_LEN + 16)))
#endif
struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs,
struct pci_device *pci);
static int read_eeprom(long ioaddr, int location);
static int read_eeprom(int location);
static void rtl_reset(struct nic *nic);
static void rtl_transmit(struct nic *nic, char *destaddr,
unsigned int type, unsigned int len, char *data);
static void rtl_transmit(struct nic *nic, const char *destaddr,
unsigned int type, unsigned int len, const char *data);
static int rtl_poll(struct nic *nic);
static void rtl_disable(struct nic*);
@ -191,13 +189,13 @@ struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs,
printf(" - ");
if (probeaddrs == 0 || probeaddrs[0] == 0) {
printf("\nERROR: no probeaddrs given, using pci_device\n");
for (p = pci; p; p++) {
for (p = pci; p->vendor; p++) {
if ( ( (p->vendor == PCI_VENDOR_ID_REALTEK)
&& (p->dev_id == PCI_DEVICE_ID_REALTEK_8139) )
|| ( (p->vendor == PCI_VENDOR_ID_SMC_1211)
&& (p->dev_id == PCI_DEVICE_ID_SMC_1211) ) ) {
probeaddrs[0] = p->ioaddr;
printf("rtl8139: probing %x (membase would be %x)\n",
printf("rtl8139: probing %x (membase %x)\n",
p->ioaddr, p->membase);
}
}
@ -210,10 +208,10 @@ struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs,
/* Bring the chip out of low-power mode. */
outb(0x00, ioaddr + Config1);
if (read_eeprom(ioaddr, 0) != 0xffff) {
if (read_eeprom(0) != 0xffff) {
unsigned short *ap = (unsigned short*)nic->node_addr;
for (i = 0; i < 3; i++)
*ap++ = read_eeprom(ioaddr, i + 7);
*ap++ = read_eeprom(i + 7);
} else {
unsigned char *ap = (unsigned char*)nic->node_addr;
for (i = 0; i < ETHER_ADDR_SIZE; i++)
@ -264,7 +262,7 @@ struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs,
#define EE_READ_CMD (6 << 6)
#define EE_ERASE_CMD (7 << 6)
static int read_eeprom(long ioaddr, int location)
static int read_eeprom(int location)
{
int i;
unsigned int retval = 0;
@ -329,7 +327,7 @@ static void rtl_reset(struct nic* nic)
* from the configuration EEPROM default, because the card manufacturer
* should have set that to match the card. */
#ifdef DEBUG_RX
#ifdef DEBUG_RX
printf("rx ring address is %X\n",(unsigned long)rx_ring);
#endif
outl((unsigned long)rx_ring, ioaddr + RxBuf);
@ -347,10 +345,10 @@ static void rtl_reset(struct nic* nic)
outw(0, ioaddr + IntrMask);
}
static void rtl_transmit(struct nic *nic, char *destaddr,
unsigned int type, unsigned int len, char *data)
static void rtl_transmit(struct nic *nic, const char *destaddr,
unsigned int type, unsigned int len, const char *data)
{
unsigned int i, status, to, nstype;
unsigned int status, to, nstype;
unsigned long txstatus;
memcpy(tx_buffer, destaddr, ETHER_ADDR_SIZE);
@ -360,7 +358,7 @@ static void rtl_transmit(struct nic *nic, char *destaddr,
memcpy(tx_buffer + ETHER_HDR_SIZE, data, len);
len += ETHER_HDR_SIZE;
#ifdef DEBUG_TX
#ifdef DEBUG_TX
printf("sending %d bytes ethtype %x\n", len, type);
#endif
@ -389,12 +387,12 @@ static void rtl_transmit(struct nic *nic, char *destaddr,
if (status & TxOK) {
cur_tx = ++cur_tx % NUM_TX_DESC;
#ifdef DEBUG_TX
#ifdef DEBUG_TX
printf("tx done (%d ticks), status %x txstatus %X\n",
to-currticks(), status, txstatus);
#endif
} else {
#ifdef DEBUG_TX
#ifdef DEBUG_TX
printf("tx timeout/error (%d ticks), status %x txstatus %X\n",
currticks()-to, status, txstatus);
#endif
@ -416,7 +414,7 @@ static int rtl_poll(struct nic *nic)
/* See below for the rest of the interrupt acknowledges. */
outw(status & ~(RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus);
#ifdef DEBUG_RX
#ifdef DEBUG_RX
printf("rtl_poll: int %x ", status);
#endif
@ -439,16 +437,16 @@ static int rtl_poll(struct nic *nic)
memcpy(nic->packet, rx_ring + ring_offs + 4, semi_count);
memcpy(nic->packet+semi_count, rx_ring, rx_size-4-semi_count);
#ifdef DEBUG_RX
#ifdef DEBUG_RX
printf("rx packet %d+%d bytes", semi_count,rx_size-4-semi_count);
#endif
} else {
memcpy(nic->packet, rx_ring + ring_offs + 4, nic->packetlen);
#ifdef DEBUG_RX
#ifdef DEBUG_RX
printf("rx packet %d bytes", rx_size-4);
#endif
}
#ifdef DEBUG_RX
#ifdef DEBUG_RX
printf(" at %X type %b%b rxstatus %x\n",
(unsigned long)(rx_ring+ring_offs+4),
nic->packet[12], nic->packet[13], rx_status);

View file

@ -30,15 +30,15 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
* The Schneider & Koch (SK) G16 Network device driver is based
* on the 'ni6510' driver from Michael Hipp which can be found at
* ftp://sunsite.unc.edu/pub/Linux/system/Network/drivers/nidrivers.tar.gz
*
*
* Sources: 1) ni6510.c by M. Hipp
* 2) depca.c by D.C. Davies
* 3) skeleton.c by D. Becker
* 4) Am7990 Local Area Network Controller for Ethernet (LANCE),
* AMD, Pub. #05698, June 1989
*
* Many Thanks for helping me to get things working to:
*
* Many Thanks for helping me to get things working to:
*
* A. Cox (A.Cox@swansea.ac.uk)
* M. Hipp (mhipp@student.uni-tuebingen.de)
* R. Bolz (Schneider & Koch, Germany)
@ -46,19 +46,19 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
* See README.sk_g16 for details about limitations and bugs for the
* current version.
*
* To Do:
* To Do:
* - Support of SK_G8 and other SK Network Cards.
* - Autoset memory mapped RAM. Check for free memory and then
* configure RAM correctly.
* configure RAM correctly.
* - SK_close should really set card in to initial state.
* - Test if IRQ 3 is not switched off. Use autoirq() functionality.
* (as in /drivers/net/skeleton.c)
* - Implement Multicast addressing. At minimum something like
* in depca.c.
* in depca.c.
* - Redo the statistics part.
* - Try to find out if the board is in 8 Bit or 16 Bit slot.
* If in 8 Bit mode don't use IRQ 11.
* - (Try to make it slightly faster.)
* - (Try to make it slightly faster.)
*/
/* to get some global routines like printf */
@ -71,23 +71,23 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
#include "sk_g16.h"
/*
* Schneider & Koch Card Definitions
/*
* Schneider & Koch Card Definitions
* =================================
*/
*/
#define SK_NAME "SK_G16"
/*
* SK_G16 Configuration
* --------------------
*/
*/
/*
/*
* Abbreviations
* -------------
*
* RAM - used for the 16KB shared memory
*
* RAM - used for the 16KB shared memory
* Boot_ROM, ROM - are used for referencing the BootEPROM
*
* SK_ADDR is a symbolic constant used to configure
@ -96,11 +96,11 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
* SK_ADDR defines the address where the RAM will be mapped into the real
* host memory.
* valid addresses are from 0xa0000 to 0xfc000 in 16Kbyte steps.
*/
*/
#define SK_ADDR 0xcc000
/*
/*
* In POS3 are bits A14-A19 of the address bus. These bits can be set
* to choose the RAM address. That's why we only can choose the RAM address
* in 16KB steps.
@ -108,12 +108,12 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
#define POS_ADDR (rom_addr>>14) /* Do not change this line */
/*
/*
* SK_G16 I/O PORT's + IRQ's + Boot_ROM locations
* ----------------------------------------------
*/
/*
/*
* As nearly every card has also SK_G16 a specified I/O Port region and
* only a few possible IRQ's.
* In the Installation Guide from Schneider & Koch is listed a possible
@ -126,14 +126,14 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
#define SK_IO_PORTS { 0x100, 0x180, 0x208, 0x220, 0x288, 0x320, 0x328, 0x390, 0 }
/*
* SK_G16 POS REGISTERS
* SK_G16 POS REGISTERS
* --------------------
*/
/*
* SK_G16 has a Programmable Option Select (POS) Register.
* The POS is composed of 8 separate registers (POS0-7) which
* are I/O mapped on an address set by the W1 switch.
* The POS is composed of 8 separate registers (POS0-7) which
* are I/O mapped on an address set by the W1 switch.
*
*/
@ -147,12 +147,12 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
/* POS5 - POS7 are unused */
/*
* SK_G16 MAC PREFIX
/*
* SK_G16 MAC PREFIX
* -----------------
*/
/*
/*
* Scheider & Koch manufacturer code (00:00:a5).
* This must be checked, that we are sure it is a SK card.
*/
@ -161,22 +161,22 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
#define SK_MAC1 0x00
#define SK_MAC2 0x5a
/*
* SK_G16 ID
/*
* SK_G16 ID
* ---------
*/
/*
* If POS0,POS1 contain the following ID, then we know
* at which I/O Port Address we are.
*/
#define SK_IDLOW 0xfd
/*
* If POS0,POS1 contain the following ID, then we know
* at which I/O Port Address we are.
*/
#define SK_IDLOW 0xfd
#define SK_IDHIGH 0x6a
/*
* LANCE POS Bit definitions
/*
* LANCE POS Bit definitions
* -------------------------
*/
@ -185,72 +185,72 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
#define SK_ROM_ON (inb(SK_POS2) & POS2_CARD)
#define SK_ROM_OFF (inb(SK_POS2) | POS2_EPROM)
#define SK_RAM_ON (inb(SK_POS2) | POS2_CARD)
#define SK_RAM_OFF (inb(SK_POS2) & POS2_EPROM)
#define SK_RAM_OFF (inb(SK_POS2) & POS2_EPROM)
#define POS2_CARD 0x0001 /* 1 = SK_G16 on 0 = off */
#define POS2_EPROM 0x0002 /* 1 = Boot EPROM off 0 = on */
#define POS2_EPROM 0x0002 /* 1 = Boot EPROM off 0 = on */
/*
/*
* SK_G16 Memory mapped Registers
* ------------------------------
*
*/
*/
#define SK_IOREG (board->ioreg) /* LANCE data registers. */
#define SK_IOREG (board->ioreg) /* LANCE data registers. */
#define SK_PORT (board->port) /* Control, Status register */
#define SK_IOCOM (board->iocom) /* I/O Command */
/*
/*
* SK_G16 Status/Control Register bits
* -----------------------------------
*
* (C) Controlreg (S) Statusreg
* (C) Controlreg (S) Statusreg
*/
/*
/*
* Register transfer: 0 = no transfer
* 1 = transferring data between LANCE and I/O reg
* 1 = transferring data between LANCE and I/O reg
*/
#define SK_IORUN 0x20
#define SK_IORUN 0x20
/*
* LANCE interrupt: 0 = LANCE interrupt occurred
/*
* LANCE interrupt: 0 = LANCE interrupt occurred
* 1 = no LANCE interrupt occurred
*/
#define SK_IRQ 0x10
#define SK_IRQ 0x10
#define SK_RESET 0x08 /* Reset SK_CARD: 0 = RESET 1 = normal */
#define SK_RW 0x02 /* 0 = write to 1 = read from */
#define SK_ADR 0x01 /* 0 = REG DataPort 1 = RAP Reg addr port */
#define SK_RREG SK_RW /* Transferdirection to read from lance */
#define SK_WREG 0 /* Transferdirection to write to lance */
#define SK_RAP SK_ADR /* Destination Register RAP */
#define SK_RDATA 0 /* Destination Register REG DataPort */
/*
* SK_G16 I/O Command
/*
* SK_G16 I/O Command
* ------------------
*/
/*
* Any bitcombination sets the internal I/O bit (transfer will start)
/*
* Any bitcombination sets the internal I/O bit (transfer will start)
* when written to I/O Command
*/
#define SK_DOIO 0x80 /* Do Transfer */
/*
* LANCE RAP (Register Address Port).
#define SK_DOIO 0x80 /* Do Transfer */
/*
* LANCE RAP (Register Address Port).
* ---------------------------------
*/
/*
* The LANCE internal registers are selected through the RAP.
/*
* The LANCE internal registers are selected through the RAP.
* The Registers are:
*
* CSR0 - Status and Control flags
* CSR0 - Status and Control flags
* CSR1 - Low order bits of initialize block (bits 15:00)
* CSR2 - High order bits of initialize block (bits 07:00, 15:08 are reserved)
* CSR3 - Allows redefinition of the Bus Master Interface.
@ -258,22 +258,22 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
* ACON = 1, BCON = 0;
*
*/
#define CSR0 0x00
#define CSR1 0x01
#define CSR2 0x02
#define CSR0 0x00
#define CSR1 0x01
#define CSR2 0x02
#define CSR3 0x03
/*
* General Definitions
/*
* General Definitions
* ===================
*/
/*
/*
* Set the number of Tx and Rx buffers, using Log_2(# buffers).
* We have 16KB RAM which can be accessed by the LANCE. In the
* We have 16KB RAM which can be accessed by the LANCE. In the
* memory are not only the buffers but also the ring descriptors and
* the initialize block.
* the initialize block.
* Don't change anything unless you really know what you do.
*/
@ -294,29 +294,29 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
* Data Buffer size is set to maximum packet length.
*/
#define PKT_BUF_SZ 1518
#define PKT_BUF_SZ 1518
/*
* The number of low I/O ports used by the ethercard.
/*
* The number of low I/O ports used by the ethercard.
*/
#define ETHERCARD_TOTAL_SIZE SK_POS_SIZE
/*
* Portreserve is there to mark the Card I/O Port region as used.
* Check_region is to check if the region at ioaddr with the size "size"
/*
* Portreserve is there to mark the Card I/O Port region as used.
* Check_region is to check if the region at ioaddr with the size "size"
* is free or not.
* Snarf_region allocates the I/O Port region.
*/
#ifndef HAVE_PORTRESERVE
#ifndef HAVE_PORTRESERVE
#define check_region(ioaddr1, size) 0
#define request_region(ioaddr1, size,name) do ; while (0)
#endif
/*
/*
* SK_DEBUG
*
* Here you can choose what level of debugging wanted.
@ -328,42 +328,42 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
* which can help to find some mistakes in configuration or even
* in the driver code.
*
* If SK_DEBUG2 is defined, many many messages will be printed
* If SK_DEBUG2 is defined, many many messages will be printed
* which normally you don't need. I used this to check the interrupt
* routine.
* routine.
*
* (If you define only SK_DEBUG2 then only the messages for
* (If you define only SK_DEBUG2 then only the messages for
* checking interrupts will be printed!)
*
* Normal way of live is:
* Normal way of live is:
*
* For the whole thing get going let both symbolic constants
* undefined. If you face any problems and you know what's going
* on (you know something about the card and you can interpret some
* hex LANCE register output) then define SK_DEBUG
*
*
*/
#undef SK_DEBUG /* debugging */
#undef SK_DEBUG2 /* debugging with more verbose report */
#ifdef SK_DEBUG
#ifdef SK_DEBUG
#define PRINTF(x) printf x
#else
#define PRINTF(x) /**/
#endif
#ifdef SK_DEBUG2
#ifdef SK_DEBUG2
#define PRINTF2(x) printf x
#else
#define PRINTF2(x) /**/
#endif
/*
/*
* SK_G16 RAM
*
* The components are memory mapped and can be set in a region from
* 0x00000 through 0xfc000 in 16KB steps.
* 0x00000 through 0xfc000 in 16KB steps.
*
* The Network components are: dual ported RAM, Prom, I/O Reg, Status-,
* Controlregister and I/O Command.
@ -376,19 +376,19 @@ Changes to make it work with Etherboot by Georg Baum <Georg.Baum@gmx.de>
* 8-Bit PROM, this means only the 16 even addresses are used of the
* 32 Byte Address region. Access to a odd address results in invalid
* data.
*
*
* LANCE I/O Reg: The I/O Reg is build of 4 single Registers, Low-Byte Write,
* Hi-Byte Write, Low-Byte Read, Hi-Byte Read.
* Transfer from or to the LANCE is always in 16Bit so Low and High
* registers are always relevant.
*
* The Data from the Readregister is not the data in the Writeregister!!
*
* Port: Status- and Controlregister.
* Two different registers which share the same address, Status is
*
* Port: Status- and Controlregister.
* Two different registers which share the same address, Status is
* read-only, Control is write-only.
*
* I/O Command:
*
* I/O Command:
* Any bitcombination written in here starts the transmission between
* Host and LANCE.
*/
@ -405,7 +405,7 @@ typedef struct
/* struct */
/*
/*
* This is the structure for the dual ported ram. We
* have exactly 16 320 Bytes. In here there must be:
*
@ -426,8 +426,8 @@ struct SK_ram
char rmdbuf[RMDNUM][PKT_BUF_SZ];
};
/*
* Structure where all necessary information is for ring buffer
/*
* Structure where all necessary information is for ring buffer
* management and statistics.
*/
@ -468,10 +468,10 @@ static void SK_reset(struct nic *nic);
static int SK_poll(struct nic *nic);
static void SK_transmit(
struct nic *nic,
char *d, /* Destination */
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p); /* Packet */
const char *p); /* Packet */
static void SK_disable(struct nic *nic);
struct nic *SK_probe(struct nic *nic, unsigned short *probe_addrs);
@ -481,19 +481,19 @@ struct nic *SK_probe(struct nic *nic, unsigned short *probe_addrs);
*/
static int SK_lance_init(struct nic *nic, unsigned short mode);
void SK_reset_board(void);
void SK_set_RAP(int reg_number);
int SK_read_reg(int reg_number);
int SK_rread_reg(void);
void SK_write_reg(int reg_number, int value);
static void SK_reset_board(void);
static void SK_set_RAP(int reg_number);
static int SK_read_reg(int reg_number);
static int SK_rread_reg(void);
static void SK_write_reg(int reg_number, int value);
/*
/*
* Debugging functions
* -------------------
*/
void SK_print_pos(struct nic *nic, char *text);
void SK_print_ram(struct nic *nic);
static void SK_print_pos(struct nic *nic, char *text);
static void SK_print_ram(struct nic *nic);
/**************************************************************************
@ -511,7 +511,7 @@ POLL - Wait for a frame
static int SK_poll(struct nic *nic)
{
/* return true if there's an ethernet packet ready to read */
struct priv *p; /* SK_G16 private structure */
struct priv *p; /* SK_G16 private structure */
struct rmd *rmdp;
int csr0, rmdstat, packet_there;
PRINTF2(("## %s: At beginning of SK_poll(). CSR0: 0x%X\n",
@ -562,7 +562,7 @@ static int SK_poll(struct nic *nic)
{
printf("%s: packet too long\n", SK_NAME);
}
/*
* All other packets will be ignored until a new frame with
* start (RX_STP) set follows.
@ -583,7 +583,7 @@ static int SK_poll(struct nic *nic)
{
int len = (rmdp->mlen & 0x0fff); /* extract message length from receive buffer */
/*
* Copy data out of our receive descriptor into nic->packet.
*
@ -592,7 +592,7 @@ static int SK_poll(struct nic *nic)
*/
memcpy(nic->packet, (unsigned char *) (rmdp->u.buffer & 0x00ffffff), nic->packetlen = len);
packet_there = 1;
packet_there = 1;
/*
@ -617,17 +617,17 @@ TRANSMIT - Transmit a frame
***************************************************************************/
static void SK_transmit(
struct nic *nic,
char *d, /* Destination */
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *pack) /* Packet */
const char *pack) /* Packet */
{
/* send the packet to destination */
struct priv *p; /* SK_G16 private structure */
struct tmd *tmdp;
short len;
int csr0, i, tmdstat;
PRINTF2(("## %s: At beginning of SK_transmit(). CSR0: 0x%X\n",
SK_NAME, SK_read_reg(CSR0)));
p = nic->priv_data;
@ -659,7 +659,7 @@ char *pack) /* Packet */
*/
tmdp->u.s.status = TX_OWN | TX_STP | TX_ENP;
/* Start Demand Transmission */
SK_write_reg(CSR0, CSR0_TDMD | CSR0_INEA);
@ -713,7 +713,7 @@ char *pack) /* Packet */
SK_lance_init(nic, MODE_NORMAL);
}
tmdp->status2 = 0; /* Clear error flags */
}
@ -798,7 +798,7 @@ int SK_probe1(struct nic *nic, short ioaddr1)
outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */
outb(POS_ADDR, SK_POS3); /* Set RAM address */
outb(SK_ROM_RAM_ON, SK_POS2); /* RAM on, BOOT_ROM on */
#ifdef SK_DEBUG
#ifdef SK_DEBUG
SK_print_pos(nic, "POS registers after ROM, RAM config");
#endif
@ -813,7 +813,7 @@ int SK_probe1(struct nic *nic, short ioaddr1)
}
/* Check for manufacturer code */
#ifdef SK_DEBUG
#ifdef SK_DEBUG
if (!(*(nic->node_addr+0) == SK_MAC0 &&
*(nic->node_addr+1) == SK_MAC1 &&
*(nic->node_addr+2) == SK_MAC2) )
@ -851,14 +851,14 @@ int SK_probe1(struct nic *nic, short ioaddr1)
for (i = 0; i < RMDNUM; i++)
{
p->rmdbufs[i] = p->ram->rmdbuf[i];
p->rmdbufs[i] = p->ram->rmdbuf[i];
}
i = 0;
if (!(i = SK_lance_init(nic, MODE_NORMAL))) /* LANCE init OK? */
{
#ifdef SK_DEBUG
#ifdef SK_DEBUG
/*
* This debug block tries to stop LANCE,
* reinit LANCE with transmitter and receiver disabled,
@ -881,7 +881,7 @@ int SK_probe1(struct nic *nic, short ioaddr1)
SK_NAME, SK_read_reg(CSR0));
SK_print_pos(nic, "POS regs before returning OK");
#endif /* SK_DEBUG */
#endif /* SK_DEBUG */
}
else /* LANCE init failed */
@ -892,10 +892,10 @@ int SK_probe1(struct nic *nic, short ioaddr1)
return -1;
}
#ifdef SK_DEBUG
#ifdef SK_DEBUG
SK_print_pos(nic, "End of SK_probe1");
SK_print_ram(nic);
#endif
#endif
return 0; /* Initialization done */
@ -915,15 +915,15 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
SK_reset_board();
/* Initialize TMD's with start values */
p->tmdnum = 0; /* First descriptor for transmitting */
p->tmdnum = 0; /* First descriptor for transmitting */
p->tmdlast = 0; /* First descriptor for reading stats */
for (i = 0; i < TMDNUM; i++) /* Init all TMD's */
{
tmdp = p->tmdhead + i;
tmdp = p->tmdhead + i;
tmdp->u.buffer = (unsigned long) p->tmdbufs[i]; /* assign buffer */
/* Mark TMD as start and end of packet */
tmdp->u.s.status = TX_STP | TX_ENP;
}
@ -932,25 +932,25 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
/* Initialize RMD's with start values */
p->rmdnum = 0; /* First RMD which will be used */
for (i = 0; i < RMDNUM; i++) /* Init all RMD's */
{
rmdp = p->rmdhead + i;
rmdp->u.buffer = (unsigned long) p->rmdbufs[i]; /* assign buffer */
/*
* LANCE must be owner at beginning so that he can fill in
* receiving packets, set status and release RMD
/*
* LANCE must be owner at beginning so that he can fill in
* receiving packets, set status and release RMD
*/
rmdp->u.s.status = RX_OWN;
rmdp->u.s.status = RX_OWN;
rmdp->blen = -PKT_BUF_SZ; /* Buffer Size in a two's complement */
rmdp->mlen = 0; /* init message length */
rmdp->mlen = 0; /* init message length */
}
/* Fill LANCE Initialize Block */
@ -965,7 +965,7 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
for (i = 0; i < 8; i++) /* Set multicast, logical address */
{
(p->ram)->ib.laddr[i] = 0; /* We do not use logical addressing */
}
}
/* Set ring descriptor pointers and set number of descriptors */
@ -975,8 +975,8 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
/* Prepare LANCE Control and Status Registers */
SK_write_reg(CSR3, CSR3_ACON); /* Ale Control !!!THIS MUST BE SET!!!! */
/*
/*
* LANCE addresses the RAM from 0x0000 to 0x3fbf and has no access to
* PC Memory locations.
*
@ -985,33 +985,33 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
* 0x0000
*
* CSR1 contains low order bits 15:0 of initialization block address
* CSR2 is built of:
* CSR2 is built of:
* 7:0 High order bits 23:16 of initialization block address
* 15:8 reserved, must be 0
*/
/* Set initialization block address (must be on word boundary) */
SK_write_reg(CSR1, 0); /* Set low order bits 15:0 */
SK_write_reg(CSR2, 0); /* Set high order bits 23:16 */
SK_write_reg(CSR2, 0); /* Set high order bits 23:16 */
PRINTF(("## %s: After setting CSR1-3. CSR0: 0x%X\n",
SK_NAME, SK_read_reg(CSR0)));
/* Initialize LANCE */
/*
/*
* INIT = Initialize, when set, causes the LANCE to begin the
* initialization procedure and access the Init Block.
*/
SK_write_reg(CSR0, CSR0_INIT);
SK_write_reg(CSR0, CSR0_INIT);
/* Wait until LANCE finished initialization */
SK_set_RAP(CSR0); /* Register Address Pointer to CSR0 */
for (i = 0; (i < 100) && !(SK_rread_reg() & CSR0_IDON); i++)
for (i = 0; (i < 100) && !(SK_rread_reg() & CSR0_IDON); i++)
; /* Wait until init done or go ahead if problems (i>=100) */
if (i >= 100) /* Something is wrong ! */
@ -1021,7 +1021,7 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
SK_NAME, (int) SK_read_reg(CSR0),
(unsigned int) &(p->ram)->ib);
#ifdef SK_DEBUG
#ifdef SK_DEBUG
SK_print_pos(nic, "LANCE INIT failed");
#endif
@ -1046,7 +1046,7 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
* ! CSR1-3 can only be accessed when in CSR0 the STOP bit is set !
*/
void SK_reset_board(void)
static void SK_reset_board(void)
{
int i;
@ -1058,17 +1058,17 @@ void SK_reset_board(void)
} /* End of SK_reset_board() */
void SK_set_RAP(int reg_number)
static void SK_set_RAP(int reg_number)
{
SK_IOREG = reg_number;
SK_PORT = SK_RESET | SK_RAP | SK_WREG;
SK_IOCOM = SK_DOIO;
while (SK_PORT & SK_IORUN)
while (SK_PORT & SK_IORUN)
;
} /* End of SK_set_RAP() */
int SK_read_reg(int reg_number)
static int SK_read_reg(int reg_number)
{
SK_set_RAP(reg_number);
@ -1081,7 +1081,7 @@ int SK_read_reg(int reg_number)
} /* End of SK_read_reg() */
int SK_rread_reg(void)
static int SK_rread_reg(void)
{
SK_PORT = SK_RESET | SK_RDATA | SK_RREG;
@ -1093,7 +1093,7 @@ int SK_rread_reg(void)
} /* End of SK_rread_reg() */
void SK_write_reg(int reg_number, int value)
static void SK_write_reg(int reg_number, int value)
{
SK_set_RAP(reg_number);
@ -1110,8 +1110,8 @@ void SK_write_reg(int reg_number, int value)
* -------------------
*/
#ifdef SK_DEBUG
void SK_print_pos(struct nic *nic, char *text)
#ifdef SK_DEBUG
static void SK_print_pos(struct nic *nic, char *text)
{
unsigned char pos0 = inb(SK_POS0),
@ -1127,20 +1127,20 @@ void SK_print_pos(struct nic *nic, char *text)
} /* End of SK_print_pos() */
void SK_print_ram(struct nic *nic)
static void SK_print_ram(struct nic *nic)
{
int i;
int i;
struct priv *p = (struct priv *) nic->priv_data;
printf("## %s: RAM Details.\n"
"## RAM at 0x%X tmdhead: 0x%X rmdhead: 0x%X initblock: 0x%X\n",
SK_NAME,
SK_NAME,
(unsigned int) p->ram,
(unsigned int) p->tmdhead,
(unsigned int) p->rmdhead,
(unsigned int) p->tmdhead,
(unsigned int) p->rmdhead,
(unsigned int) &(p->ram)->ib);
printf("## ");
for(i = 0; i < TMDNUM; i++)
@ -1160,7 +1160,7 @@ void SK_print_ram(struct nic *nic)
printf("\n## ");
}
printf("rmdbufs%d: 0x%X ", (i+1), (int) p->rmdbufs[i]);
}
}
putchar('\n');
} /* End of SK_print_ram() */

View file

@ -4,30 +4,30 @@
* of the GNU Public License, incorporated herein by reference.
*
* Module : sk_g16.h
* Version : $Revision$
* Version : $Revision$
*
* Author : M.Hipp (mhipp@student.uni-tuebingen.de)
* changes by : Patrick J.D. Weichmann
*
* Date Created : 94/05/25
*
* Description : In here are all necessary definitions of
* Description : In here are all necessary definitions of
* the am7990 (LANCE) chip used for writing a
* network device driver which uses this chip
* network device driver which uses this chip
*
* $Log$
* Revision 1.1 2000-02-07 06:30:07 okuji
* add missing files.
* Revision 1.2 2000-04-22 01:17:09 okuji
* update the network support to etherboot-4.5.8.
*
-*/
#ifndef SK_G16_H
#ifndef SK_G16_H
#define SK_G16_H
/*
* Control and Status Register 0 (CSR0) bit definitions
* Control and Status Register 0 (CSR0) bit definitions
*
* (R=Readable) (W=Writeable) (S=Set on write) (C-Clear on write)
*
@ -37,16 +37,16 @@
#define CSR0_BABL 0x4000 /* Babble transmitter timeout error (RC) */
#define CSR0_CERR 0x2000 /* Collision Error (RC) */
#define CSR0_MISS 0x1000 /* Missed packet (RC) */
#define CSR0_MERR 0x0800 /* Memory Error (RC) */
#define CSR0_MERR 0x0800 /* Memory Error (RC) */
#define CSR0_RINT 0x0400 /* Receiver Interrupt (RC) */
#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */
#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */
#define CSR0_IDON 0x0100 /* Initialization Done (RC) */
#define CSR0_INTR 0x0080 /* Interrupt Flag (R) */
#define CSR0_INEA 0x0040 /* Interrupt Enable (RW) */
#define CSR0_RXON 0x0020 /* Receiver on (R) */
#define CSR0_TXON 0x0010 /* Transmitter on (R) */
#define CSR0_TDMD 0x0008 /* Transmit Demand (RS) */
#define CSR0_STOP 0x0004 /* Stop (RS) */
#define CSR0_STOP 0x0004 /* Stop (RS) */
#define CSR0_STRT 0x0002 /* Start (RS) */
#define CSR0_INIT 0x0001 /* Initialize (RS) */
@ -67,24 +67,24 @@
#define MODE_PROM 0x8000 /* Promiscuous Mode */
#define MODE_INTL 0x0040 /* Internal Loopback */
#define MODE_DRTY 0x0020 /* Disable Retry */
#define MODE_DRTY 0x0020 /* Disable Retry */
#define MODE_COLL 0x0010 /* Force Collision */
#define MODE_DTCR 0x0008 /* Disable Transmit CRC) */
#define MODE_LOOP 0x0004 /* Loopback */
#define MODE_DTX 0x0002 /* Disable the Transmitter */
#define MODE_DTX 0x0002 /* Disable the Transmitter */
#define MODE_DRX 0x0001 /* Disable the Receiver */
#define MODE_NORMAL 0x0000 /* Normal operation mode */
#define MODE_NORMAL 0x0000 /* Normal operation mode */
/*
* Receive message descriptor status bit definitions.
* Receive message descriptor status bit definitions.
*/
#define RX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */
#define RX_ERR 0x40 /* Error Summary */
#define RX_FRAM 0x20 /* Framing Error */
#define RX_OFLO 0x10 /* Overflow Error */
#define RX_CRC 0x08 /* CRC Error */
#define RX_CRC 0x08 /* CRC Error */
#define RX_BUFF 0x04 /* Buffer Error */
#define RX_STP 0x02 /* Start of Packet */
#define RX_ENP 0x01 /* End of Packet */
@ -99,28 +99,28 @@
#define TX_MORE 0x10 /* More the 1 retry needed to Xmit */
#define TX_ONE 0x08 /* One retry needed to Xmit */
#define TX_DEF 0x04 /* Deferred */
#define TX_STP 0x02 /* Start of Packet */
#define TX_STP 0x02 /* Start of Packet */
#define TX_ENP 0x01 /* End of Packet */
/*
* Transmit status (2) (valid if TX_ERR == 1)
*/
#define TX_BUFF 0x8000 /* Buffering error (no ENP) */
#define TX_UFLO 0x4000 /* Underflow (late memory) */
#define TX_LCOL 0x1000 /* Late collision */
#define TX_LCAR 0x0400 /* Loss of Carrier */
#define TX_RTRY 0x0200 /* Failed after 16 retransmissions */
#define TX_BUFF 0x8000 /* Buffering error (no ENP) */
#define TX_UFLO 0x4000 /* Underflow (late memory) */
#define TX_LCOL 0x1000 /* Late collision */
#define TX_LCAR 0x0400 /* Loss of Carrier */
#define TX_RTRY 0x0200 /* Failed after 16 retransmissions */
#define TX_TDR 0x003f /* Time-domain-reflectometer-value */
/*
* Structures used for Communication with the LANCE
/*
* Structures used for Communication with the LANCE
*/
/* LANCE Initialize Block */
struct init_block
struct init_block
{
unsigned short mode; /* Mode Register */
unsigned char paddr[6]; /* Physical Address (MAC) */
@ -132,14 +132,14 @@ struct init_block
/* Receive Message Descriptor Entry */
struct rmd
{
struct rmd
{
union rmd_u
{
unsigned long buffer; /* Address of buffer */
struct rmd_s
{
unsigned char unused[3];
unsigned char unused[3];
unsigned volatile char status; /* Status Bits */
} s;
} u;
@ -150,7 +150,7 @@ struct rmd
/* Transmit Message Descriptor Entry */
struct tmd
struct tmd
{
union tmd_u
{
@ -165,4 +165,4 @@ struct tmd
unsigned volatile short status2; /* Error Status Bits */
};
#endif /* End of SK_G16_H */
#endif /* End of SK_G16_H */

View file

@ -12,16 +12,16 @@
* "Features" of the SMC chip:
* 4608 byte packet memory. ( for the 91C92/4. Others have more )
* EEPROM for configuration
* AUI/TP selection
* AUI/TP selection
*
* Authors
* Erik Stahlman <erik@vt.edu>
* Erik Stahlman <erik@vt.edu>
* Daniel Engström <daniel.engstrom@riksnett.no>
*
*
* History
* 98-09-25 Daniel Engström Etherboot driver crated from Eric's
* Linux driver.
*
* Linux driver.
*
*---------------------------------------------------------------------------*/
#define LINUX_OUT_MACROS 1
#define SMC9000_VERBOSE 1
@ -29,39 +29,40 @@
#include "etherboot.h"
#include "nic.h"
#include "cards.h"
#include "smc9000.h"
# define _outb outb
# define _outw outw
# define _outw outw
static const char smc9000_version[] = "Version 0.99 98-09-30";
static unsigned int smc9000_base=0;
static const char *interfaces[ 2 ] = { "TP", "AUI" };
static const char *chip_ids[ 15 ] = {
NULL, NULL, NULL,
static const char *chip_ids[ 15 ] = {
NULL, NULL, NULL,
/* 3 */ "SMC91C90/91C92",
/* 4 */ "SMC91C94",
/* 5 */ "SMC91C95",
NULL,
/* 7 */ "SMC91C100",
/* 8 */ "SMC91C100FD",
NULL, NULL, NULL,
/* 7 */ "SMC91C100",
/* 8 */ "SMC91C100FD",
NULL, NULL, NULL,
NULL, NULL, NULL
};
};
static const char smc91c96_id[] = "SMC91C96";
/*
* Function: smc_reset( int ioaddr )
* Purpose:
* This sets the SMC91xx chip to its normal state, hopefully from whatever
* mess that any other DOS driver has put it in.
* This sets the SMC91xx chip to its normal state, hopefully from whatever
* mess that any other DOS driver has put it in.
*
* Maybe I should reset more registers to defaults in here? SOFTRESET should
* do that for me.
*
* Method:
* 1. send a SOFT RESET
* 2. wait for it to finish
* 2. wait for it to finish
* 3. reset the memory management unit
* 4. clear all interrupts
*
@ -72,19 +73,19 @@ static void smc_reset(int ioaddr)
* affect EEPROM. That seems unnecessary */
SMC_SELECT_BANK(ioaddr, 0);
_outw( RCR_SOFTRESET, ioaddr + RCR );
/* this should pause enough for the chip to be happy */
SMC_DELAY(ioaddr);
/* Set the transmit and receive configuration registers to
* default values */
_outw(RCR_CLEAR, ioaddr + RCR);
_outw(TCR_CLEAR, ioaddr + TCR);
/* Reset the MMU */
SMC_SELECT_BANK(ioaddr, 2);
_outw( MC_RESET, ioaddr + MMU_CMD );
/* Note: It doesn't seem that waiting for the MMU busy is needed here,
* but this is a place where future chipsets _COULD_ break. Be wary
* of issuing another MMU command right after this */
@ -101,7 +102,7 @@ static void smc_reset(int ioaddr)
*
* Algorithm:
* (1) see if the high byte of BANK_SELECT is 0x33
* (2) compare the ioaddr with the base register's address
* (2) compare the ioaddr with the base register's address
* (3) see if I recognize the chip ID in the appropriate register
*
* ---------------------------------------------------------------------
@ -111,7 +112,7 @@ static int smc_probe( int ioaddr )
word bank;
word revision_register;
word base_address_register;
/* First, see if the high byte is 0x33 */
bank = inw(ioaddr + BANK_SELECT);
if ((bank & 0xFF00) != 0x3300) {
@ -132,7 +133,7 @@ static int smc_probe( int ioaddr )
base_address_register = inw(ioaddr + BASE);
if (ioaddr != (base_address_register >> 3 & 0x3E0)) {
#ifdef SMC9000_VERBOSE
#ifdef SMC9000_VERBOSE
printf("SMC9000: IOADDR %x doesn't match configuration (%x)."
"Probably not a SMC chip\n",
ioaddr, base_address_register >> 3 & 0x3E0);
@ -150,13 +151,13 @@ static int smc_probe( int ioaddr )
revision_register = inw(ioaddr + REVISION);
if (!chip_ids[(revision_register >> 4) & 0xF]) {
/* I don't recognize this chip, so... */
#ifdef SMC9000_VERBOSE
#ifdef SMC9000_VERBOSE
printf("SMC9000: IO %x: Unrecognized revision register:"
" %x, Contact author.\n", ioaddr, revision_register);
#endif
return -1;
}
/* at this point I'll assume that the chip is an SMC9xxx.
* It might be prudent to check a listing of MAC addresses
* against the hardware address, or do some other tests. */
@ -178,26 +179,26 @@ static void smc9000_reset(struct nic *nic)
***************************************************************************/
static void smc9000_transmit(
struct nic *nic,
char *d, /* Destination */
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
const char *p) /* Packet */
{
word length; /* real, length incl. header */
word length; /* real, length incl. header */
word numPages;
long time_out;
unsigned long time_out;
byte packet_no;
word status;
int i;
/* We dont pad here since we can have the hardware doing it for us */
length = (s + ETHER_HDR_SIZE + 1)&~1;
/* convert to MMU pages */
numPages = length / 256;
if (numPages > 7 ) {
#ifdef SMC9000_VERBOSE
#ifdef SMC9000_VERBOSE
printf("SMC9000: Far too big packet error. \n");
#endif
return;
@ -208,10 +209,10 @@ static void smc9000_transmit(
/* now, try to allocate the memory */
SMC_SELECT_BANK(smc9000_base, 2);
_outw(MC_ALLOC | numPages, smc9000_base + MMU_CMD);
status = 0;
/* wait for the memory allocation to finnish */
for (time_out = currticks() + 5*TICKS_PER_SEC; (currticks() - time_out) < 0; ) {
for (time_out = currticks() + 5*TICKS_PER_SEC; currticks() < time_out; ) {
status = inb(smc9000_base + INTERRUPT);
if ( status & IM_ALLOC_INT ) {
/* acknowledge the interrupt */
@ -219,8 +220,8 @@ static void smc9000_transmit(
break;
}
}
if ((status & IM_ALLOC_INT) != 0 ) {
if ((status & IM_ALLOC_INT) != 0 ) {
/* We've got the memory */
break;
} else {
@ -228,7 +229,7 @@ static void smc9000_transmit(
_outw(MC_RESET, smc9000_base + MMU_CMD);
}
}
/* If I get here, I _know_ there is a packet slot waiting for me */
packet_no = inb(smc9000_base + PNR_ARR + 1);
if (packet_no & 0x80) {
@ -236,35 +237,35 @@ static void smc9000_transmit(
printf("SMC9000: Memory allocation failed. \n");
return;
}
/* we have a packet address, so tell the card to use it */
_outb(packet_no, smc9000_base + PNR_ARR);
/* point to the beginning of the packet */
_outw(PTR_AUTOINC, smc9000_base + POINTER);
#if SMC9000_DEBUG > 2
#if SMC9000_DEBUG > 2
printf("Trying to xmit packet of length %x\n", length );
#endif
/* send the packet length ( +6 for status, length and ctl byte )
* and the status word ( set to zeros ) */
_outw(0, smc9000_base + DATA_1 );
/* send the packet length ( +6 for status words, length, and ctl) */
_outb((length+6) & 0xFF, smc9000_base + DATA_1);
_outb((length+6) >> 8 , smc9000_base + DATA_1);
/* Write the contents of the packet */
/* The ethernet header first... */
outsw(smc9000_base + DATA_1, d, ETHER_ADDR_SIZE >> 1);
outsw(smc9000_base + DATA_1, nic->node_addr, ETHER_ADDR_SIZE >> 1);
_outw(htons(t), smc9000_base + DATA_1);
/* ... the data ... */
/* ... the data ... */
outsw(smc9000_base + DATA_1 , p, s >> 1);
/* ... and the last byte, if there is one. */
if ((s & 1) == 0) {
_outw(0, smc9000_base + DATA_1);
@ -272,48 +273,48 @@ static void smc9000_transmit(
_outb(p[s-1], smc9000_base + DATA_1);
_outb(0x20, smc9000_base + DATA_1);
}
/* and let the chipset deal with it */
_outw(MC_ENQUEUE , smc9000_base + MMU_CMD);
status = 0; time_out = currticks() + 5*TICKS_PER_SEC;
do {
status = inb(smc9000_base + INTERRUPT);
if ((status & IM_TX_INT ) != 0) {
word tx_status;
/* ack interrupt */
_outb(IM_TX_INT, smc9000_base + INTERRUPT);
packet_no = inw(smc9000_base + FIFO_PORTS);
packet_no &= 0x7F;
/* select this as the packet to read from */
_outb( packet_no, smc9000_base + PNR_ARR );
/* read the first word from this packet */
_outw( PTR_AUTOINC | PTR_READ, smc9000_base + POINTER );
tx_status = inw( smc9000_base + DATA_1 );
if (0 == (tx_status & TS_SUCCESS)) {
#ifdef SMC9000_VERBOSE
if (0 == (tx_status & TS_SUCCESS)) {
#ifdef SMC9000_VERBOSE
printf("SMC9000: TX FAIL STATUS: %x \n", tx_status);
#endif
/* re-enable transmit */
SMC_SELECT_BANK(smc9000_base, 0);
_outw(inw(smc9000_base + TCR ) | TCR_ENABLE, smc9000_base + TCR );
}
/* kill the packet */
SMC_SELECT_BANK(smc9000_base, 2);
_outw(MC_FREEPKT, smc9000_base + MMU_CMD);
return;
}
}while(currticks() - time_out < 0);
}while(currticks() < time_out);
printf("SMC9000: Waring TX timed out, resetting board\n");
smc_reset(smc9000_base);
return;
@ -324,26 +325,24 @@ static void smc9000_transmit(
***************************************************************************/
static int smc9000_poll(struct nic *nic)
{
word status;
if(!smc9000_base)
return 0;
SMC_SELECT_BANK(smc9000_base, 2);
SMC_SELECT_BANK(smc9000_base, 2);
if (inw(smc9000_base + FIFO_PORTS) & FP_RXEMPTY)
return 0;
/* start reading from the start of the packet */
_outw(PTR_READ | PTR_RCV | PTR_AUTOINC, smc9000_base + POINTER);
/* First read the status and check that we're ok */
if (!(inw(smc9000_base + DATA_1) & RS_ERRORS)) {
if (!(inw(smc9000_base + DATA_1) & RS_ERRORS)) {
/* Next: read the packet length and mask off the top bits */
nic->packetlen = (inw(smc9000_base + DATA_1) & 0x07ff);
nic->packetlen = (inw(smc9000_base + DATA_1) & 0x07ff);
/* the packet length includes the 3 extra words */
nic->packetlen -= 6;
#if SMC9000_DEBUG > 2
#if SMC9000_DEBUG > 2
printf(" Reading %d words (and %d byte(s))\n",
(nic->packetlen >> 1), nic->packetlen & 1);
#endif
@ -352,12 +351,12 @@ static int smc9000_poll(struct nic *nic)
/* is there an odd last byte ? */
if (nic->packet[nic->packetlen+1] & 0x20)
nic->packetlen++;
/* error or good, tell the card to get rid of this packet */
_outw(MC_RELEASE, smc9000_base + MMU_CMD);
return 1;
return 1;
}
printf("SMC9000: RX error\n");
/* error or good, tell the card to get rid of this packet */
_outw(MC_RELEASE, smc9000_base + MMU_CMD);
@ -368,11 +367,11 @@ static void smc9000_disable(struct nic *nic)
{
if(!smc9000_base)
return;
/* no more interrupts for me */
SMC_SELECT_BANK(smc9000_base, 2);
_outb( 0, smc9000_base + INT_MASK);
/* and tell the card to stay away from that nasty outside world */
SMC_SELECT_BANK(smc9000_base, 0);
_outb( RCR_CLEAR, smc9000_base + RCR );
@ -389,62 +388,61 @@ struct nic *smc9000_probe(struct nic *nic, unsigned short *probe_addrs)
int memory;
int media;
const char * version_string;
const char * if_string;
int irqval;
int i;
const char * if_string;
int i;
/*
* the SMC9000 can be at any of the following port addresses. To change,
* for a slightly different card, you can add it to the array. Keep in
* mind that the array must end in zero.
*/
static unsigned short portlist[] = {
#ifdef SMC9000_SCAN
SMC9000_SCAN,
#ifdef SMC9000_SCAN
SMC9000_SCAN,
#else
0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0,
0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0,
#endif
0 };
printf("\nSMC9000 %s\n", smc9000_version);
#ifdef SMC9000_VERBOSE
#ifdef SMC9000_VERBOSE
printf("Copyright (C) 1998 Daniel Engstr\x94m\n");
printf("Copyright (C) 1996 Eric Stahlman\n");
#endif
/* if no addresses supplied, fall back on defaults */
if (probe_addrs == 0 || probe_addrs[0] == 0)
probe_addrs = portlist;
/* check every ethernet address */
for (i = 0; probe_addrs[i]; i++) {
/* check this specific address */
if (smc_probe(probe_addrs[i]) == 0)
if (smc_probe(probe_addrs[i]) == 0)
smc9000_base = probe_addrs[i];
}
/* couldn't find anything */
if(0 == smc9000_base)
if(0 == smc9000_base)
goto out;
/*
* Get the MAC address ( bank 1, regs 4 - 9 )
*/
SMC_SELECT_BANK(smc9000_base, 1);
for ( i = 0; i < 6; i += 2 ) {
word address;
address = inw(smc9000_base + ADDR0 + i);
nic->node_addr[i+1] = address >> 8;
nic->node_addr[i] = address & 0xFF;
}
/* get the memory information */
/* get the memory information */
SMC_SELECT_BANK(smc9000_base, 0);
memory = ( inw(smc9000_base + MCR) >> 9 ) & 0x7; /* multiplier */
memory *= 256 * (inw(smc9000_base + MIR) & 0xFF);
/*
* Now, I want to find out more about the chip. This is sort of
* redundant, but it's cleaner to have it in both, rather than having
@ -453,19 +451,19 @@ struct nic *smc9000_probe(struct nic *nic, unsigned short *probe_addrs)
SMC_SELECT_BANK(smc9000_base, 3);
revision = inw(smc9000_base + REVISION);
version_string = chip_ids[(revision >> 4) & 0xF];
if (((revision & 0xF0) >> 4 == CHIP_9196) &&
if (((revision & 0xF0) >> 4 == CHIP_9196) &&
((revision & 0x0F) >= REV_9196)) {
/* This is a 91c96. 'c96 has the same chip id as 'c94 (4) but
* a revision starting at 6 */
version_string = smc91c96_id;
}
if ( !version_string ) {
/* I shouldn't get here because this call was done before.... */
goto out;
}
/* is it using AUI or 10BaseT ? */
SMC_SELECT_BANK(smc9000_base, 1);
if (inw(smc9000_base + CONFIG) & CFG_AUI_SELECT)
@ -474,12 +472,12 @@ struct nic *smc9000_probe(struct nic *nic, unsigned short *probe_addrs)
media = 1;
if_string = interfaces[media - 1];
/* now, reset the chip, and put it into a known state */
smc_reset(smc9000_base);
printf("%s rev:%d I/O port:%x Interface:%s RAM:%d bytes \n",
version_string, revision & 0xF,
version_string, revision & 0xF,
smc9000_base, if_string, memory );
/*
* Print the Ethernet address
@ -488,14 +486,14 @@ struct nic *smc9000_probe(struct nic *nic, unsigned short *probe_addrs)
for (i = 0; i < 5; i++)
printf("%b:", nic->node_addr[i]);
printf("%b\n", nic->node_addr[5]);
SMC_SELECT_BANK(smc9000_base, 0);
/* see the header file for options in TCR/RCR NORMAL*/
_outw(TCR_NORMAL, smc9000_base + TCR);
_outw(RCR_NORMAL, smc9000_base + RCR);
/* Select which interface to use */
/* Select which interface to use */
SMC_SELECT_BANK(smc9000_base, 1);
if ( media == 1 ) {
_outw( inw( smc9000_base + CONFIG ) & ~CFG_AUI_SELECT,
@ -510,12 +508,12 @@ struct nic *smc9000_probe(struct nic *nic, unsigned short *probe_addrs)
nic->poll = smc9000_poll;
nic->transmit = smc9000_transmit;
nic->disable = smc9000_disable;
return nic;
out:
#ifdef SMC9000_VERBOSE
#ifdef SMC9000_VERBOSE
printf("No SMC9000 adapters found\n");
#endif
smc9000_base = 0;

View file

@ -1,85 +1,85 @@
/*------------------------------------------------------------------------
* smc9000.h
*
*
* Copyright (C) 1998 by Daniel Engström
* Copyright (C) 1996 by Erik Stahlman
* Copyright (C) 1996 by Erik Stahlman
*
* This software may be used and distributed according to the terms
* of the GNU Public License, incorporated herein by reference.
*
* This file contains register information and access macros for
* the SMC91xxx chipset.
*
* Information contained in this file was obtained from the SMC91C94
* manual from SMC. To get a copy, if you really want one, you can find
* This file contains register information and access macros for
* the SMC91xxx chipset.
*
* Information contained in this file was obtained from the SMC91C94
* manual from SMC. To get a copy, if you really want one, you can find
* information under www.smsc.com in the components division.
* ( this thanks to advice from Donald Becker ).
*
*
* Authors
* Daniel Engström <daniel.engstrom@riksnett.no>
* Erik Stahlman <erik@vt.edu>
* Erik Stahlman <erik@vt.edu>
*
* History
* 96-01-06 Erik Stahlman moved definitions here from main .c
* 96-01-06 Erik Stahlman moved definitions here from main .c
* file
* 96-01-19 Erik Stahlman polished this up some, and added
* 96-01-19 Erik Stahlman polished this up some, and added
* better error handling
* 98-09-25 Daniel Engström adjusted for Etherboot
* 98-09-27 Daniel Engström moved some static strings back to the
* main .c file
* --------------------------------------------------------------------------*/
#ifndef _SMC9000_H_
#ifndef _SMC9000_H_
# define _SMC9000_H_
/* I want some simple types */
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long int dword;
typedef unsigned long int dword;
/*---------------------------------------------------------------
*
*
* A description of the SMC registers is probably in order here,
* although for details, the SMC datasheet is invaluable.
*
* although for details, the SMC datasheet is invaluable.
*
* Basically, the chip has 4 banks of registers ( 0 to 3 ), which
* are accessed by writing a number into the BANK_SELECT register
* ( I also use a SMC_SELECT_BANK macro for this ).
*
*
* The banks are configured so that for most purposes, bank 2 is all
* that is needed for simple run time tasks.
* that is needed for simple run time tasks.
* ----------------------------------------------------------------------*/
/*
* Bank Select Register:
* Bank Select Register:
*
* yyyy yyyy 0000 00xx
* xx = bank number
* yyyy yyyy 0000 00xx
* xx = bank number
* yyyy yyyy = 0x33, for identification purposes.
*/
#define BANK_SELECT 14
/* BANK 0 */
#define TCR 0 /* transmit control register */
#define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
#define TCR_FDUPLX 0x0800 /* receive packets sent out */
#define TCR 0 /* transmit control register */
#define TCR_ENABLE 0x0001 /* if this is 1, we can transmit */
#define TCR_FDUPLX 0x0800 /* receive packets sent out */
#define TCR_STP_SQET 0x1000 /* stop transmitting if Signal quality error */
#define TCR_MON_CNS 0x0400 /* monitors the carrier status */
#define TCR_PAD_ENABLE 0x0080 /* pads short packets to 64 bytes */
#define TCR_CLEAR 0 /* do NOTHING */
/* the normal settings for the TCR register : */
#define TCR_NORMAL (TCR_ENABLE | TCR_PAD_ENABLE)
/* the normal settings for the TCR register : */
#define TCR_NORMAL (TCR_ENABLE | TCR_PAD_ENABLE)
#define EPH_STATUS 2
#define ES_LINK_OK 0x4000 /* is the link integrity ok ? */
#define RCR 4
#define RCR_SOFTRESET 0x8000 /* resets the chip */
#define RCR_SOFTRESET 0x8000 /* resets the chip */
#define RCR_STRIP_CRC 0x200 /* strips CRC */
#define RCR_ENABLE 0x100 /* IFF this is set, we can receive packets */
#define RCR_ALMUL 0x4 /* receive all multicast packets */
#define RCR_ALMUL 0x4 /* receive all multicast packets */
#define RCR_PROMISC 0x2 /* enable promiscuous mode */
/* the normal settings for the RCR register : */
@ -93,7 +93,7 @@ typedef unsigned long int dword;
/* BANK 1 */
#define CONFIG 0
#define CFG_AUI_SELECT 0x100
#define CFG_AUI_SELECT 0x100
#define BASE 2
#define ADDR0 4
#define ADDR1 6
@ -111,23 +111,23 @@ typedef unsigned long int dword;
#define MMU_CMD 0
#define MC_BUSY 1 /* only readable bit in the register */
#define MC_NOP 0
#define MC_ALLOC 0x20 /* or with number of 256 byte packets */
#define MC_RESET 0x40
#define MC_REMOVE 0x60 /* remove the current rx packet */
#define MC_RELEASE 0x80 /* remove and release the current rx packet */
#define MC_FREEPKT 0xA0 /* Release packet in PNR register */
#define MC_ENQUEUE 0xC0 /* Enqueue the packet for transmit */
#define MC_ALLOC 0x20 /* or with number of 256 byte packets */
#define MC_RESET 0x40
#define MC_REMOVE 0x60 /* remove the current rx packet */
#define MC_RELEASE 0x80 /* remove and release the current rx packet */
#define MC_FREEPKT 0xA0 /* Release packet in PNR register */
#define MC_ENQUEUE 0xC0 /* Enqueue the packet for transmit */
#define PNR_ARR 2
#define FIFO_PORTS 4
#define FP_RXEMPTY 0x8000
#define FP_TXEMPTY 0x80
#define FP_RXEMPTY 0x8000
#define FP_TXEMPTY 0x80
#define POINTER 6
#define PTR_READ 0x2000
#define PTR_RCV 0x8000
#define PTR_AUTOINC 0x4000
#define PTR_AUTOINC 0x4000
#define PTR_AUTO_INC 0x0040
#define DATA_1 8
@ -137,11 +137,11 @@ typedef unsigned long int dword;
#define INT_MASK 13
#define IM_RCV_INT 0x1
#define IM_TX_INT 0x2
#define IM_TX_EMPTY_INT 0x4
#define IM_TX_EMPTY_INT 0x4
#define IM_ALLOC_INT 0x8
#define IM_RX_OVRN_INT 0x10
#define IM_EPH_INT 0x20
#define IM_ERCV_INT 0x40 /* not on SMC9192 */
#define IM_ERCV_INT 0x40 /* not on SMC9192 */
/* BANK 3 */
#define MULTICAST1 0
@ -160,19 +160,19 @@ typedef unsigned long int dword;
#define CHIP_9190 3
#define CHIP_9194 4
#define CHIP_9195 5
#define CHIP_9196 4
#define CHIP_9196 4
#define CHIP_91100 7
#define CHIP_91100FD 8
#define CHIP_91100FD 8
#define REV_9196 6
#define REV_9196 6
/*
* Transmit status bits
/*
* Transmit status bits
*/
#define TS_SUCCESS 0x0001
#define TS_LOSTCAR 0x0400
#define TS_LATCOL 0x0200
#define TS_16COL 0x0010
#define TS_SUCCESS 0x0001
#define TS_LOSTCAR 0x0400
#define TS_LATCOL 0x0200
#define TS_16COL 0x0010
/*
* Receive status bits
@ -183,23 +183,23 @@ typedef unsigned long int dword;
#define RS_TOOLONG 0x0800
#define RS_TOOSHORT 0x0400
#define RS_MULTICAST 0x0001
#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
#define RS_ERRORS (RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT)
/*-------------------------------------------------------------------------
* I define some macros to make it easier to do somewhat common
* or slightly complicated, repeated tasks.
* or slightly complicated, repeated tasks.
--------------------------------------------------------------------------*/
/* select a register bank, 0 to 3 */
#define SMC_SELECT_BANK(x, y) { _outw( y, x + BANK_SELECT ); }
#define SMC_SELECT_BANK(x, y) { _outw( y, x + BANK_SELECT ); }
/* define a small delay for the reset */
#define SMC_DELAY(x) { inw( x + RCR );\
inw( x + RCR );\
inw( x + RCR ); }
inw( x + RCR );\
inw( x + RCR ); }
#endif /* _SMC_9000_H_ */
#endif /* _SMC_9000_H_ */

View file

@ -21,6 +21,7 @@ Fujitsu MB86960 spec sheet (different chip but same family)
#include "etherboot.h"
/* to get the interface to the body of the program */
#include "nic.h"
#include "cards.h"
/*
EtherStar I/O Register offsets
@ -159,10 +160,10 @@ TRANSMIT - Transmit a frame
***************************************************************************/
static void tiara_transmit(
struct nic *nic,
char *d, /* Destination */
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
char *p) /* Packet */
const char *p) /* Packet */
{
unsigned int len;
unsigned long time;
@ -203,7 +204,7 @@ static int tiara_probe1(struct nic *nic)
/* Hope all the Tiara cards have this vendor prefix */
static char vendor_prefix[] = { 0x08, 0x00, 0x1A };
static char all_ones[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
int i, b;
int i;
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
nic->node_addr[i] = inb(ioaddr + PROM_ID + i);

View file

@ -1,380 +1,699 @@
/*
Etherboot DEC Tulip driver
adapted by Ken Yap from
/*
Tulip and clone Etherboot Driver
By Marty Connor (mdc@thinguin.org)
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
FreeBSD netboot DEC 21143 driver
Based on Ken Yap's Tulip Etherboot Driver and Donald Becker's
Linux Tulip Driver. Supports N-Way speed auto-configuration on
MX98715, MX98715A and MX98725. Support inexpensive PCI 10/100 cards
based on the Macronix MX987x5 chip, such as the SOHOware Fast
model SFA110A, and the LinkSYS model LNE100TX. The NetGear
model FA310X, based on the LC82C168 chip is supported.
The TRENDnet TE100-PCIA NIC which uses a genuine Intel 21143-PD
chipset is supported.
Author: David Sharp
date: Nov/98
Documentation and source code used:
Source for Etherboot driver at
http://etherboot.sourceforge.net/
MX98715A Data Sheet and MX98715A Application Note
on http://www.macronix.com/ (PDF format files)
Source for Linux tulip driver at
http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html
Known to work on DEC DE500 using 21143-PC chipset.
Even on cards with the same chipset there can be
incompatablity problems with the way media selection
and status LED settings are done. See comments below.
Some code fragments were taken from verious places,
Ken Yap's etherboot, FreeBSD's if_de.c, and various
Linux related files. DEC's manuals for the 21143 and
SROM format were very helpful. The Linux de driver
development page has a number of links to useful
related information. Have a look at:
ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html
Adapted by Ken Yap from
FreeBSD netboot DEC 21143 driver
Author: David Sharp
date: Nov/98
Some code fragments were taken from verious places, Ken Yap's
etherboot, FreeBSD's if_de.c, and various Linux related files.
DEC's manuals for the 21143 and SROM format were very helpful.
The Linux de driver development page has a number of links to
useful related information. Have a look at:
ftp://cesdis.gsfc.nasa.gov/pub/linux/drivers/tulip-devel.html
*/
/*********************************************************************/
/* Revision History */
/*********************************************************************/
/*
29 Feb 2000 mdc 0.75b7
Increased reset delay to 3 seconds because Macronix cards seem to
need more reset time before card comes back to a usable state.
26 Feb 2000 mdc 0.75b6
Added a 1 second delay after initializing the transmitter because
some cards seem to need the time or they drop the first packet
transmitted.
23 Feb 2000 mdc 0.75b5
removed udelay code and used currticks() for more reliable delay
code in reset pause and sanity timeouts. Added function prototypes
and TX debugging code.
21 Feb 2000 mdc patch to Etherboot 4.4.3
Incorporated patches from Bob Edwards and Paul Mackerras of
Linuxcare's OZLabs to deal with inefficiencies in tulip_transmit
and udelay. We now wait for packet transmission to complete
(or sanity timeout).
04 Feb 2000 Robert.Edwards@anu.edu.au patch to Etherboot 4.4.2
patch to tulip.c that implements the automatic selection of the MII
interface on cards using the Intel/DEC 21143 reference design, in
particular, the TRENDnet TE100-PCIA NIC which uses a genuine Intel
21143-PD chipset.
11 Jan 2000 mdc 0.75b4
Added support for NetGear FA310TX card based on the LC82C168
chip. This should also support Lite-On LC82C168 boards.
Added simple MII support. Re-arranged code to better modularize
initializations.
04 Dec 1999 mdc 0.75b3
Added preliminary support for LNE100TX PCI cards. Should work for
PNIC2 cards. No MII support, but single interface (RJ45) tulip
cards seem to not care.
03 Dec 1999 mdc 0.75b2
Renamed from mx987x5 to tulip, merged in original tulip init code
from tulip.c to support other tulip compatible cards.
02 Dec 1999 mdc 0.75b1
Released Beta MX987x5 Driver for code review and testing to netboot
and thinguin mailing lists.
*/
/*********************************************************************/
/* Declarations */
/*********************************************************************/
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#include "tulip.h"
#include "cards.h"
#undef TULIP_DEBUG
#undef TULIP_DEBUG_WHERE
#define TX_TIME_OUT 2*TICKS_PER_SEC
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
/* Register offsets for tulip device */
enum tulip_offsets {
CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0
};
#define DEC_21142_CSR6_TTM 0x00400000 /* Transmit Threshold Mode */
#define DEC_21142_CSR6_HBD 0x00080000 /* Heartbeat Disable */
#define DEC_21142_CSR6_PS 0x00040000 /* Port Select */
/* EEPROM Address width definitions */
#define EEPROM_ADDRLEN 6
#define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */
/* Data Read from the EEPROM */
static unsigned char ee_data[EEPROM_SIZE];
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << addr_len)
#define EE_READ_CMD (6 << addr_len)
#define EE_ERASE_CMD (7 << addr_len)
/* EEPROM_Ctrl bits. */
#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */
#define EE_CS 0x01 /* 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. Even at 33Mhz current PCI
implementations don't overrun the EEPROM clock. We add a bus
turn-around to insure that this remains true. */
#define eeprom_delay() inl(ee_addr)
/* helpful macro if on a big_endian machine for changing byte order.
not strictly needed on Intel */
#define le16_to_cpu(val) (val)
/* transmit and receive descriptor format */
struct txdesc {
volatile unsigned long status; /* owner, status */
unsigned long buf1sz:11, /* size of buffer 1 */
buf2sz:11, /* size of buffer 2 */
control:10; /* control bits */
const unsigned char *buf1addr; /* buffer 1 address */
const unsigned char *buf2addr; /* buffer 2 address */
};
struct rxdesc {
volatile unsigned long status; /* owner, status */
unsigned long buf1sz:11, /* size of buffer 1 */
buf2sz:11, /* size of buffer 2 */
control:10; /* control bits */
unsigned char *buf1addr; /* buffer 1 address */
unsigned char *buf2addr; /* buffer 2 address */
};
/* Size of transmit and receive buffers */
#define BUFLEN 1536
/*********************************************************************/
/* Global Storage */
/*********************************************************************/
/* PCI Bus parameters */
static unsigned short vendor, dev_id;
static unsigned short ioaddr;
static unsigned int *membase;
static unsigned long devfn;
static unsigned char srom[1024];
static unsigned long ioaddr;
#define BUFLEN 1600 /* must be longword divisable */
/* buffers must be longword aligned */
/* Note: transmit and receive buffers must be longword aligned and
longword divisable */
/* transmit descriptor and buffer */
static struct txrxdesc txd;
static unsigned char txb[BUFLEN];
static struct txdesc txd __attribute__ ((aligned(4)));
#ifndef USE_INTERNAL_BUFFER
#define txb ((char *)0x10000 - BUFLEN)
#else
static unsigned char txb[BUFLEN] __attribute__ ((aligned(4)));
#endif
/* receive descriptor(s) and buffer(s) */
#define NRXD 4
static struct txrxdesc rxd[NRXD];
static int rxd_tail = 0;
static unsigned char rxb[NRXD][BUFLEN];
static struct rxdesc rxd[NRXD] __attribute__ ((aligned(4)));
#ifndef USE_INTERNAL_BUFFER
#define rxb ((char *)0x10000 - NRXD * BUFLEN - BUFLEN)
#else
static unsigned char rxb[NRXD * BUFLEN] __attribute__ ((aligned(4)));
#endif
static int rxd_tail;
static unsigned char ehdr[ETHER_HDR_SIZE]; /* buffer for ethernet header */
/* buffer for ethernet header */
static unsigned char ehdr[ETHER_HDR_SIZE];
enum tulip_offsets {
CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58,
CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78 };
/*********************************************************************/
/* Function Prototypes */
/*********************************************************************/
static void whereami(const char *str);
static int lc82c168_mdio_read(int phy_id, int location);
static void lc82c168_mdio_write(int phy_id, int location, int value);
static void lc82c168_do_mii();
static int read_eeprom(unsigned long ioaddr, int location, int addr_len);
struct nic *tulip_probe(struct nic *nic, unsigned short *io_addrs,
struct pci_device *pci);
static void tulip_init_ring(struct nic *nic);
static void tulip_reset(struct nic *nic);
static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
unsigned int s, const char *p);
static int tulip_poll(struct nic *nic);
static void tulip_disable(struct nic *nic);
static void whereami (const char *str);
#ifdef TULIP_DEBUG
static void tulip_more(void);
#endif /* TULIP_DEBUG */
static void tulip_wait(unsigned int nticks);
/*********************************************************************/
/* Utility Routines */
/*********************************************************************/
/***************************************************************************/
/* 21143 specific stuff */
/***************************************************************************/
/* XXX assume 33MHz PCI bus, this is not very accurate and should be
used only with gross over estimations of required delay times unless
you tune UADJUST to your specific processor and I/O subsystem */
#define UADJUST 870
static void udelay(unsigned long usec) {
unsigned long i;
for (i=((usec*UADJUST)/33)+1; i>0; i--) (void) TULIP_CSR_READ(csr_0);
static inline void whereami (const char *str)
{
#ifdef TULIP_DEBUG_WHERE
printf("%s\n", str);
/* sleep(2); */
#endif
}
/* The following srom related code was taken from FreeBSD's if_de.c */
/* with minor alterations to make it work here. the Linux code is */
/* better but this was easier to use */
static void delay_300ns()
#ifdef TULIP_DEBUG
static void tulip_more()
{
int idx;
for (idx = (300 / 33) + 1; idx > 0; idx--)
(void) TULIP_CSR_READ(csr_busmode);
printf("\n\n-- more --");
while (!iskey())
/* wait */;
getchar();
printf("\n\n");
}
#endif /* TULIP_DEBUG */
static void tulip_wait(unsigned int nticks)
{
unsigned int to = currticks() + nticks;
while (currticks() < to)
/* wait */ ;
}
#define EMIT do { TULIP_CSR_WRITE(csr_srom_mii, csr); delay_300ns(); } while (0)
static void srom_idle()
/*********************************************************************/
/* Media Descriptor Code */
/*********************************************************************/
static int lc82c168_mdio_read(int phy_id, int location)
{
unsigned bit, csr;
int i = 1000;
int retval = 0;
csr = SROMSEL ; EMIT;
csr = SROMSEL | SROMRD; EMIT;
csr ^= SROMCS; EMIT;
csr ^= SROMCLKON; EMIT;
/*
* Write 25 cycles of 0 which will force the SROM to be idle.
*/
for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) {
csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
csr ^= SROMCLKON; EMIT; /* clock high; data valid */
whereami("mdio_read\n");
outl(0x60020000 | (phy_id<<23) | (location<<18), ioaddr + 0xA0);
inl(ioaddr + 0xA0);
inl(ioaddr + 0xA0);
while (--i > 0)
if ( ! ((retval = inl(ioaddr + 0xA0)) & 0x80000000))
return retval & 0xFFFF;
if (i == 0) printf("mdio read timeout!\n");
return 0xFFFF;
}
static void lc82c168_mdio_write(int phy_id, int location, int value)
{
int i = 1000;
int cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
whereami("mdio_write\n");
outl(cmd, ioaddr + 0xA0);
do
if ( ! (inl(ioaddr + 0xA0) & 0x80000000))
break;
while (--i > 0);
if (i == 0) printf("mdio write timeout!\n");
return;
}
static void lc82c168_do_mii(void)
{
int phy, phy_idx;
whereami("do_mii\n");
for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < 4; phy++) {
int mii_status = lc82c168_mdio_read(phy, 1);
if ((mii_status & 0x8301) == 0x8001 ||
((mii_status & 0x8000) == 0 && (mii_status & 0x7800) != 0)) {
int mii_reg0 = lc82c168_mdio_read(phy, 0);
int mii_advert = lc82c168_mdio_read(phy, 4);
int mii_reg4 = ((mii_status >> 6) & 0x01E1) | 1;
phy_idx++;
printf("%s: MII trcvr #%d "
"config %x status %x advertising %x reg4 %x.\n",
"LC82C168", phy, mii_reg0, mii_status, mii_advert, mii_reg4);
lc82c168_mdio_write(phy, 0, mii_reg0 | 0x1000);
if (mii_advert != mii_reg4)
lc82c168_mdio_write(phy, 4, mii_reg4);
}
csr ^= SROMCLKOFF; EMIT;
csr ^= SROMCS; EMIT;
csr = 0; EMIT;
}
#ifdef TULIP_DEBUG
printf("mii_cnt = %d\n", phy_idx);
#endif
}
static void srom_read()
/*********************************************************************/
/* EEPROM Reading Code */
/*********************************************************************/
/* EEPROM routines adapted from the Linux Tulip Code */
/* Reading a serial EEPROM is a "bit" grungy, but we work our way
through:->.
*/
static int read_eeprom(unsigned long ioaddr, int location, int addr_len)
{
unsigned idx;
const unsigned bitwidth = SROM_BITWIDTH;
const unsigned cmdmask = (SROMCMD_RD << bitwidth);
const unsigned msb = 1 << (bitwidth + 3 - 1);
unsigned lastidx = (1 << bitwidth) - 1;
int i;
unsigned short retval = 0;
long ee_addr = ioaddr + CSR9;
int read_cmd = location | EE_READ_CMD;
srom_idle();
whereami("read_eeprom\n");
for (idx = 0; idx <= lastidx; idx++) {
unsigned lastbit, data, bits, bit, csr;
csr = SROMSEL ; EMIT;
csr = SROMSEL | SROMRD; EMIT;
csr ^= SROMCSON; EMIT;
csr ^= SROMCLKON; EMIT;
outl(EE_ENB & ~EE_CS, ee_addr);
outl(EE_ENB, ee_addr);
lastbit = 0;
for (bits = idx|cmdmask, bit = bitwidth + 3; bit > 0; bit--, bits <<= 1)
{
const unsigned thisbit = bits & msb;
csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
if (thisbit != lastbit) {
csr ^= SROMDOUT; EMIT; /* clock low; invert data */
} else {
EMIT;
}
csr ^= SROMCLKON; EMIT; /* clock high; data valid */
lastbit = thisbit;
}
csr ^= SROMCLKOFF; EMIT;
/* Shift the read command bits out. */
for (i = 4 + addr_len; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
outl(EE_ENB | dataval, ee_addr);
eeprom_delay();
outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay();
}
outl(EE_ENB, ee_addr);
for (data = 0, bits = 0; bits < 16; bits++) {
data <<= 1;
csr ^= SROMCLKON; EMIT; /* clock high; data valid */
data |= TULIP_CSR_READ(csr_srom_mii) & SROMDIN ? 1 : 0;
csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */
}
srom[idx*2] = data & 0xFF;
srom[idx*2+1] = data >> 8;
csr = SROMSEL | SROMRD; EMIT;
csr = 0; EMIT;
}
srom_idle();
for (i = 16; i > 0; i--) {
outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay();
retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0);
outl(EE_ENB, ee_addr);
eeprom_delay();
}
/* Terminate the EEPROM access. */
outl(EE_ENB & ~EE_CS, ee_addr);
return retval;
}
/*********************************************************************/
/* tulip_init_ring - setup the tx and rx descriptors */
/*********************************************************************/
static void tulip_init_ring(struct nic *nic)
{
int i;
/**************************************************************************
ETH_RESET - Reset adapter
***************************************************************************/
/* setup the transmit descriptor */
txd.buf1addr = &txb[0];
txd.buf2addr = &txb[0]; /* just in case */
txd.buf1sz = 192; /* setup packet must be 192 bytes */
txd.buf2sz = 0;
txd.control = 0x028; /* setup packet + TER */
txd.status = 0x80000000; /* give ownership to device */
/* construct perfect filter frame with mac address as first match
and broadcast address for all others */
for (i=0; i<192; i++) txb[i] = 0xFF;
txb[0] = nic->node_addr[0];
txb[1] = nic->node_addr[1];
txb[4] = nic->node_addr[2];
txb[5] = nic->node_addr[3];
txb[8] = nic->node_addr[4];
txb[9] = nic->node_addr[5];
/* setup receive descriptor */
for (i=0; i<NRXD; i++) {
rxd[i].buf1addr = &rxb[i * BUFLEN];
rxd[i].buf2addr = 0; /* not used */
rxd[i].buf1sz = BUFLEN;
rxd[i].buf2sz = 0; /* not used */
rxd[i].control = 0x0;
rxd[i].status = 0x80000000; /* give ownership to device */
}
/* Set Receive end of ring on last descriptor */
rxd[NRXD - 1].control = 0x008;
rxd_tail = 0;
}
/*********************************************************************/
/* eth_reset - Reset adapter */
/*********************************************************************/
static void tulip_reset(struct nic *nic)
{
int x,cnt=2;
unsigned long csr6,csr15;
unsigned long to, csr6;
outl(0x00000001, ioaddr + CSR0);
udelay(1000);
/* turn off reset and set cache align=16lword, burst=unlimit */
outl(0x01A08000, ioaddr + CSR0);
whereami("tulip_reset\n");
/* for some reason the media selection does not take
the first time se it is repeated. */
/* Stop Tx and RX */
outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
while(cnt--) {
/* stop TX,RX processes */
if (cnt == 1)
outl(0x32404000, ioaddr + CSR6);
else
outl(0x32000040, ioaddr + CSR6);
if (vendor == PCI_VENDOR_ID_MACRONIX && dev_id == PCI_DEVICE_ID_MX987x5) {
/* set up 10-BASE-T Control Port */
outl(0xFFFFFFFF, ioaddr + CSR14);
/* set up 10-BASE-T Status Port */
outl(0x00001000, ioaddr + CSR12);
/* Set Operation Control Register (CSR6) for MX987x5
to allow N-Way Active Speed selection, and
start the chip's Tx to process setup frame.
While it is possible to force speed selection,
this is probably more useful most of the time.
*/
outl(0x01A80200, ioaddr + CSR6);
/* XXX - media selection is vendor specific and hard coded right
here. This should be fixed to use the hints in the SROM and
allow media selection by the user at runtime. MII support
should also be added. Support for chips other than the
21143 should be added here as well */
} else if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_LC82C115) {
/* This is MX987x5 init code. It seems to work for the LNE100TX
but should be replaced when we figure out the right way
to do this initialization
*/
outl(0xFFFFFFFF, ioaddr + CSR14);
outl(0x00001000, ioaddr + CSR12);
outl(0x01A80200, ioaddr + CSR6);
/* start set to 10Mbps half-duplex */
} else if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_DEC_TULIP) {
/* setup SIA */
outl(0x0, ioaddr + CSR13); /* reset SIA */
outl(0x7f3f, ioaddr + CSR14);
outl(0x8000008, ioaddr + CSR15);
outl(0x0, ioaddr + CSR13);
outl(0x1, ioaddr + CSR13);
outl(0x2404000, ioaddr + CSR6);
lc82c168_do_mii();
/* initalize GP */
outl(0x8af0008, ioaddr + CSR15);
outl(0x50008, ioaddr + CSR15);
} else if (vendor == PCI_VENDOR_ID_DEC && dev_id == PCI_DEVICE_ID_DEC_21142) {
/* nothing */
} else {
/* If we don't know what to do with the card, set to 10Mbps half-duplex */
/* end set to 10Mbps half-duplex */
outl(0x00000000, ioaddr + CSR13);
outl(0x7F3F0000, ioaddr + CSR14);
outl(0x08000008, ioaddr + CSR15);
outl(0x00000000, ioaddr + CSR13);
outl(0x00000001, ioaddr + CSR13);
outl(0x02404000, ioaddr + CSR6);
outl(0x08AF0008, ioaddr + CSR15);
outl(0x00050008, ioaddr + CSR15);
if (vendor == PCI_VENDOR_ID_MACRONIX && dev_id == PCI_DEVICE_ID_MX987x5) {
/* do stuff for MX98715 */
outl(0x01a80000, ioaddr + CSR6);
outl(0xFFFFFFFF, ioaddr + CSR14);
outl(0x00001000, ioaddr + CSR12);
}
outl(0x0, ioaddr + CSR7); /* disable interrupts */
}
/* construct setup packet which is used by the 21143 to
program its CAM to recognize interesting MAC addresses */
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
outl(0x00000001, ioaddr + CSR0);
memset(&txd, 0, sizeof(struct txrxdesc));
txd.buf1addr = &txb[0];
txd.buf2addr = &txb[0]; /* just in case */
txd.buf1sz = 192; /* setup packet must be 192 bytes */
txd.buf2sz = 0;
txd.control = 0x020; /* setup packet */
txd.status = 0x80000000; /* give ownership to 21143 */
tulip_wait(3*TICKS_PER_SEC);
/* construct perfect filter frame */
/* with mac address as first match */
/* and broadcast address for all others */
/* turn off reset and set cache align=16lword, burst=unlimit */
outl(0x01A08000, ioaddr + CSR0);
for(x=0;x<192;x++) txb[x] = 0xff;
txb[0] = nic->node_addr[0];
txb[1] = nic->node_addr[1];
txb[4] = nic->node_addr[2];
txb[5] = nic->node_addr[3];
txb[8] = nic->node_addr[4];
txb[9] = nic->node_addr[5];
outl((unsigned long)&txd, ioaddr + CSR4); /* set xmit buf */
outl(0x2406000, ioaddr + CSR6); /* start transmiter */
/* set up transmit and receive descriptors */
tulip_init_ring(nic);
udelay(50000); /* wait for the setup packet to be processed */
/* Point to receive descriptor */
outl((unsigned long)&rxd[0], ioaddr + CSR3);
outl((unsigned long)&txd , ioaddr + CSR4);
}
csr6 = 0x02404000;
/* setup receive descriptor */
{
int x;
for(x=0;x<NRXD;x++) {
memset(&rxd[x], 0, sizeof(struct txrxdesc));
rxd[x].buf1addr = &rxb[x][0];
rxd[x].buf2addr = 0; /* not used */
rxd[x].buf1sz = BUFLEN;
rxd[x].buf2sz = 0; /* not used */
rxd[x].control = 0x0;
rxd[x].status = 0x80000000; /* give ownership it to 21143 */
}
rxd[NRXD - 1].control = 0x008; /* Set Receive end of ring on la
st descriptor */
rxd_tail = 0;
}
/* Chip specific init code */
/* tell DC211XX where to find rx descriptor list */
outl((unsigned long)&rxd[0], ioaddr + CSR3);
/* start the receiver */
outl(0x2406002, ioaddr + CSR6);
if (vendor == PCI_VENDOR_ID_MACRONIX && dev_id == PCI_DEVICE_ID_MX987x5) {
csr6 = 0x01880200;
/* Set CSR16 and CSR20 to values that allow device modification */
outl(0x0B3C0000 | inl(ioaddr + CSR16), ioaddr + CSR16);
outl(0x00011000 | inl(ioaddr + CSR20), ioaddr + CSR20);
} else if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_LC82C115) {
/* This is MX987x5 init code. It seems to work for the LNE100TX
but should be replaced when we figure out the right way
to do this initialization.
*/
csr6 = 0x01880200;
outl(0x0B3C0000 | inl(ioaddr + CSR16), ioaddr + CSR16);
outl(0x00011000 | inl(ioaddr + CSR20), ioaddr + CSR20);
} else if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_DEC_TULIP) {
csr6 = 0x814C0000;
outl(0x00000001, ioaddr + CSR15);
} else if (vendor == PCI_VENDOR_ID_DEC && dev_id == PCI_DEVICE_ID_DEC_21142) {
/* check SROM for evidence of an MII interface */
/* get Controller_0 Info Leaf Offset from SROM - assume already in ee_data */
int offset = ee_data [27] + (ee_data [28] << 8);
/* check offset range and if we have an extended type 3 Info Block */
if ((offset >= 30) && (offset < 120) && (ee_data [offset + 3] > 128) &&
(ee_data [offset + 4] == 3)) {
/* must have an MII interface - disable heartbeat, select port etc. */
csr6 |= (DEC_21142_CSR6_HBD | DEC_21142_CSR6_PS);
csr6 &= ~(DEC_21142_CSR6_TTM);
}
}
/* set the chip's operating mode */
outl(csr6, ioaddr + CSR6);
/* Start Tx */
outl(inl(ioaddr + CSR6) | 0x00002000, ioaddr + CSR6);
/* immediate transmit demand */
outl(0, ioaddr + CSR1);
to = currticks() + TX_TIME_OUT;
while ((txd.status & 0x80000000) && (currticks() < to))
/* wait */ ;
if (currticks() >= to) {
printf ("TX Setup Timeout!\n");
}
#ifdef TULIP_DEBUG
printf("txd.status = %X\n", txd.status);
printf("ticks = %d\n", currticks() - (to - TX_TIME_OUT));
tulip_more();
#endif
/* enable RX */
outl(inl(ioaddr + CSR6) | 0x00000002, ioaddr + CSR6);
/* immediate poll demand */
outl(0, ioaddr + CSR2);
}
/**************************************************************************
ETH_TRANSMIT - Transmit a frame
***************************************************************************/
static const char padmap[] = {
0, 3, 2, 1};
static void tulip_transmit(struct nic *nic, char *d, unsigned int t, unsigned int s, char *p)
/*********************************************************************/
/* eth_transmit - Transmit a frame */
/*********************************************************************/
static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,
unsigned int s, const char *p)
{
unsigned int len;
int pad;
int status;
unsigned char c;
unsigned long time;
unsigned long to;
/* setup ethernet header */
whereami("tulip_transmit\n");
memcpy(ehdr, d, ETHER_ADDR_SIZE);
memcpy(&ehdr[ETHER_ADDR_SIZE], nic->node_addr, ETHER_ADDR_SIZE);
ehdr[ETHER_ADDR_SIZE*2] = (t >> 8) & 0xff;
ehdr[ETHER_ADDR_SIZE*2+1] = t & 0xff;
/* Stop Tx */
outl(inl(ioaddr + CSR6) & ~0x00002000, ioaddr + CSR6);
/* setup the transmit descriptor */
/* setup ethernet header */
memcpy(ehdr, d, ETHER_ADDR_SIZE);
memcpy(&ehdr[ETHER_ADDR_SIZE], nic->node_addr, ETHER_ADDR_SIZE);
ehdr[ETHER_ADDR_SIZE*2] = (t >> 8) & 0xFF;
ehdr[ETHER_ADDR_SIZE*2+1] = t & 0xFF;
memset(&txd, 0, sizeof(struct txrxdesc));
/* setup the transmit descriptor */
txd.buf1addr = &ehdr[0]; /* ethernet header */
txd.buf1sz = ETHER_HDR_SIZE;
txd.buf2addr = p; /* packet to transmit */
txd.buf2sz = s;
txd.control = 0x00000188; /* LS+FS+TER */
txd.status = 0x80000000; /* give ownership to device */
txd.buf1addr = &ehdr[0]; /* ethernet header */
txd.buf1sz = ETHER_HDR_SIZE;
/* Point to transmit descriptor */
outl((unsigned long)&txd, ioaddr + CSR4);
txd.buf2addr = p; /* packet to transmit */
txd.buf2sz = s;
/* Start Tx */
outl(inl(ioaddr + CSR6) | 0x00002000, ioaddr + CSR6);
txd.control = 0x188; /* LS+FS+TER */
/* immediate transmit demand */
outl(0, ioaddr + CSR1);
txd.status = 0x80000000; /* give it to 21143 */
to = currticks() + TX_TIME_OUT;
while ((txd.status & 0x80000000) && (currticks() < to))
/* wait */ ;
outl(inl(ioaddr + CSR6) & ~0x00004000, ioaddr + CSR6);
outl((unsigned long)&txd, ioaddr + CSR4);
outl(inl(ioaddr + CSR6) | 0x00004000, ioaddr + CSR6);
/* Wait for transmit to complete before returning. not well tested.
time = currticks();
while(txd.status & 0x80000000) {
if (currticks() - time > 20) {
printf("transmit timeout.\n");
break;
}
}
*/
if (currticks() >= to) {
printf ("TX Timeout!\n");
}
}
/**************************************************************************
ETH_POLL - Wait for a frame
***************************************************************************/
/*********************************************************************/
/* eth_poll - Wait for a frame */
/*********************************************************************/
static int tulip_poll(struct nic *nic)
{
/* common variables */
unsigned short type = 0;
int x;
whereami("tulip_poll\n");
if (rxd[rxd_tail].status & 0x80000000) return 0;
if (rxd[rxd_tail].status & 0x80000000)
return 0;
nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16;
whereami("tulip_poll got one\n");
/* copy packet to working buffer */
/* XXX - this copy could be avoided with a little more work
but for now we are content with it because the optimised
memcpy(, , ) is quite fast */
nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16;
memcpy(nic->packet, &rxb[rxd_tail][0], nic->packetlen);
/* copy packet to working buffer */
/* XXX - this copy could be avoided with a little more work
but for now we are content with it because the optimised
memcpy is quite fast */
/* return the descriptor and buffer to recieve ring */
rxd[rxd_tail].status = 0x80000000;
rxd_tail++;
if (rxd_tail == NRXD) rxd_tail = 0;
memcpy(nic->packet, rxb + rxd_tail * BUFLEN, nic->packetlen);
return 1;
/* return the descriptor and buffer to receive ring */
rxd[rxd_tail].status = 0x80000000;
rxd_tail++;
if (rxd_tail == NRXD) rxd_tail = 0;
return 1;
}
/*********************************************************************/
/* eth_disable - Disable the interface */
/*********************************************************************/
static void tulip_disable(struct nic *nic)
{
/* nothing for the moment */
whereami("tulip_disable\n");
/* The other Etherboot drivers don't seem to do anything here,
so for now, we will not either */
#if 0
/* disable interrupts */
outl(0x00000000, ioaddr + CSR7);
/* Stop the chip's Tx and Rx processes. */
outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
/* Clear the missed-packet counter. */
(volatile unsigned long)inl(ioaddr + CSR8);
#endif
}
/*********************************************************************/
/* eth_probe - Look for an adapter */
/*********************************************************************/
struct nic *tulip_probe(struct nic *nic, unsigned short *io_addrs,
struct pci_device *pci)
{
unsigned int i;
/**************************************************************************
ETH_PROBE - Look for an adapter
***************************************************************************/
struct nic *tulip_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci)
{
int i;
whereami("tulip_probe\n");
if (io_addrs == 0 || *io_addrs == 0)
return (0);
vendor = pci->vendor;
dev_id = pci->dev_id;
ioaddr = *io_addrs;
membase = (unsigned int *)pci->membase;
if (io_addrs == 0 || *io_addrs == 0)
return 0;
/* wakeup chip */
pcibios_write_config_dword(0,pci->devfn,0x40,0x00000000);
vendor = pci->vendor;
dev_id = pci->dev_id;
ioaddr = *io_addrs;
/* Stop the chip's Tx and Rx processes. */
/* outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6); */
/* Clear the missed-packet counter. */
/* (volatile int)inl(ioaddr + CSR8); */
/* wakeup chip */
pcibios_write_config_dword(0, pci->devfn, 0x40, 0x00000000);
srom_read();
/* Stop the chip's Tx and Rx processes. */
outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
for (i=0; i < 6; i++)
nic->node_addr[i] = srom[20+i];
/* Clear the missed-packet counter. */
(volatile unsigned long)inl(ioaddr + CSR8);
printf("Tulip %b:%b:%b:%b:%b:%b at ioaddr 0x%x\n",
srom[20],srom[21],srom[22],srom[23],srom[24],srom[25],
ioaddr);
/* Get MAC Address */
tulip_reset(nic);
/* Hardware Address retrieval method for LC82C168 */
if (vendor == PCI_VENDOR_ID_LINKSYS && dev_id == PCI_DEVICE_ID_DEC_TULIP) {
for (i = 0; i < 3; i++) {
int value, boguscnt = 100000;
outl(0x600 | i, ioaddr + 0x98);
do
value = inl(ioaddr + CSR9);
while (value < 0 && --boguscnt > 0);
nic->node_addr[i*2] = (u8)((value >> 8) & 0xFF);
nic->node_addr[i*2 + 1] = (u8)( value & 0xFF);
}
} else {
/* read EEPROM data */
for (i = 0; i < sizeof(ee_data)/2; i++)
((unsigned short *)ee_data)[i] =
le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN));
nic->reset = tulip_reset;
nic->poll = tulip_poll;
nic->transmit = tulip_transmit;
nic->disable = tulip_disable;
return nic;
/* extract MAC address from EEPROM buffer */
for (i=0; i<6; i++)
nic->node_addr[i] = ee_data[20+i];
}
printf("Tulip %b:%b:%b:%b:%b:%b at ioaddr 0x%x\n",
nic->node_addr[0],nic->node_addr[1],nic->node_addr[2],nic->node_addr[3],
nic->node_addr[4],nic->node_addr[5],ioaddr);
/* initialize device */
tulip_reset(nic);
nic->reset = tulip_reset;
nic->poll = tulip_poll;
nic->transmit = tulip_transmit;
nic->disable = tulip_disable;
return nic;
}

View file

@ -1,67 +0,0 @@
/* mostly stolen from FreeBSD if_de.c, if_devar.h */
#define TULIP_CSR_READ(csr) (membase[csr*2])
#define CSR_READ(csr) (membase[csr*2])
#define TULIP_CSR_WRITE(csr, val) (membase[csr*2] = val)
#define CSR_WRITE(csr, val) (membase[csr*2] = val)
#define csr_0 0
#define csr_1 1
#define csr_2 2
#define csr_3 3
#define csr_4 4
#define csr_5 5
#define csr_6 6
#define csr_7 7
#define csr_8 8
#define csr_9 9
#define csr_10 10
#define csr_11 11
#define csr_12 12
#define csr_13 13
#define csr_14 14
#define csr_15 15
#define csr_busmode csr_0
#define csr_txpoll csr_1
#define csr_rxpoll csr_2
#define csr_rxlist csr_3
#define csr_txlist csr_4
#define csr_status csr_5
#define csr_command csr_6
#define csr_intr csr_7
#define csr_missed_frames csr_8
#define csr_enetrom csr_9 /* 21040 */
#define csr_reserved csr_10 /* 21040 */
#define csr_full_duplex csr_11 /* 21040 */
#define csr_bootrom csr_10 /* 21041/21140A/?? */
#define csr_gp csr_12 /* 21140* */
#define csr_watchdog csr_15 /* 21140* */
#define csr_gp_timer csr_11 /* 21041/21140* */
#define csr_srom_mii csr_9 /* 21041/21140* */
#define csr_sia_status csr_12 /* 2104x */
#define csr_sia_connectivity csr_13 /* 2104x */
#define csr_sia_tx_rx csr_14 /* 2104x */
#define csr_sia_general csr_15 /* 2104x */
#define SROMSEL 0x0800
#define SROMCS 0x0001
#define SROMCLKON 0x0002
#define SROMCLKOFF 0x0002
#define SROMRD 0x4000
#define SROMWR 0x2000
#define SROM_BITWIDTH 6
#define SROMCMD_RD 6
#define SROMCSON 0x0001
#define SROMDOUT 0x0004
#define SROMDIN 0x0008
struct txrxdesc {
unsigned long status; /* owner, status */
unsigned long buf1sz:11, /* size of buffer 1 */
buf2sz:11, /* size of buffer 2 */
control:10; /* control bits */
unsigned char *buf1addr; /* buffer 1 address */
unsigned char *buf2addr; /* buffer 2 address */
};

View file

@ -1,6 +1,13 @@
This software may be used and distributed according to the terms of
the GNU Public License, incorporated herein by reference.
This is a tulip and clone driver for Etherboot. See the revision
history in the tulip.c file for information on changes. This version
of the driver incorporates changes from Bob Edwards and Paul Mackerras
who cantributed changes to support the TRENDnet TE100-PCIA NIC which
uses a genuine Intel 21143-PD chipset. There are also various code
cleanups to make time-based activities more reliable.
Of course you have to have all the usual Etherboot environment
(bootp/dhcp/NFS) set up, and you need a Linux kernel with v0.91g
(7.16.99) or later of the tulip.c driver compiled in to support some
@ -8,9 +15,6 @@ MX98715 based cards. That file is available at:
http://cesdis.gsfc.nasa.gov/linux/drivers/test/tulip.c
See the comments at the beginning of ntulip.c for more information
on the code.
NOTES
I've tested this driver with a SOHOware Fast 10/100 Model SDA110A,
@ -46,3 +50,4 @@ Regards,
Marty Connor
mdc@thinguin.org
http://www.thinguin.org/

View file

@ -16,8 +16,6 @@
This driver is designed for the VIA VT86C100A Rhine-II PCI Fast Ethernet
controller.
TODO: Some block comments are C++ style. Can get away with it
with gcc, but not nice.
*/
static const char *version = "rhine.c v1.0.0 2000-01-07\n";
@ -48,370 +46,371 @@ static const char *version = "rhine.c v1.0.0 2000-01-07\n";
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#include "cards.h"
/* define all ioaddr */
#define byPAR0 ioaddr
#define byRCR ioaddr + 6
#define byTCR ioaddr + 7
#define byCR0 ioaddr + 8
#define byCR1 ioaddr + 9
#define byISR0 ioaddr + 0x0c
#define byISR1 ioaddr + 0x0d
#define byIMR0 ioaddr + 0x0e
#define byIMR1 ioaddr + 0x0f
#define byMAR0 ioaddr + 0x10
#define byMAR1 ioaddr + 0x11
#define byMAR2 ioaddr + 0x12
#define byMAR3 ioaddr + 0x13
#define byMAR4 ioaddr + 0x14
#define byMAR5 ioaddr + 0x15
#define byMAR6 ioaddr + 0x16
#define byMAR7 ioaddr + 0x17
#define dwCurrentRxDescAddr ioaddr + 0x18
#define dwCurrentTxDescAddr ioaddr + 0x1c
#define dwCurrentRDSE0 ioaddr + 0x20
#define dwCurrentRDSE1 ioaddr + 0x24
#define dwCurrentRDSE2 ioaddr + 0x28
#define dwCurrentRDSE3 ioaddr + 0x2c
#define dwNextRDSE0 ioaddr + 0x30
#define dwNextRDSE1 ioaddr + 0x34
#define dwNextRDSE2 ioaddr + 0x38
#define dwNextRDSE3 ioaddr + 0x3c
#define dwCurrentTDSE0 ioaddr + 0x40
#define dwCurrentTDSE1 ioaddr + 0x44
#define dwCurrentTDSE2 ioaddr + 0x48
#define dwCurrentTDSE3 ioaddr + 0x4c
#define dwNextTDSE0 ioaddr + 0x50
#define dwNextTDSE1 ioaddr + 0x54
#define dwNextTDSE2 ioaddr + 0x58
#define dwNextTDSE3 ioaddr + 0x5c
#define dwCurrRxDMAPtr ioaddr + 0x60
#define dwCurrTxDMAPtr ioaddr + 0x64
#define byMPHY ioaddr + 0x6c
#define byMIISR ioaddr + 0x6d
#define byBCR0 ioaddr + 0x6e
#define byBCR1 ioaddr + 0x6f
#define byMIICR ioaddr + 0x70
#define byMIIAD ioaddr + 0x71
#define wMIIDATA ioaddr + 0x72
#define byEECSR ioaddr + 0x74
#define byTEST ioaddr + 0x75
#define byGPIO ioaddr + 0x76
#define byCFGA ioaddr + 0x78
#define byCFGB ioaddr + 0x79
#define byCFGC ioaddr + 0x7a
#define byCFGD ioaddr + 0x7b
#define wTallyCntMPA ioaddr + 0x7c
#define wTallyCntCRC ioaddr + 0x7d
#define byPAR0 ioaddr
#define byRCR ioaddr + 6
#define byTCR ioaddr + 7
#define byCR0 ioaddr + 8
#define byCR1 ioaddr + 9
#define byISR0 ioaddr + 0x0c
#define byISR1 ioaddr + 0x0d
#define byIMR0 ioaddr + 0x0e
#define byIMR1 ioaddr + 0x0f
#define byMAR0 ioaddr + 0x10
#define byMAR1 ioaddr + 0x11
#define byMAR2 ioaddr + 0x12
#define byMAR3 ioaddr + 0x13
#define byMAR4 ioaddr + 0x14
#define byMAR5 ioaddr + 0x15
#define byMAR6 ioaddr + 0x16
#define byMAR7 ioaddr + 0x17
#define dwCurrentRxDescAddr ioaddr + 0x18
#define dwCurrentTxDescAddr ioaddr + 0x1c
#define dwCurrentRDSE0 ioaddr + 0x20
#define dwCurrentRDSE1 ioaddr + 0x24
#define dwCurrentRDSE2 ioaddr + 0x28
#define dwCurrentRDSE3 ioaddr + 0x2c
#define dwNextRDSE0 ioaddr + 0x30
#define dwNextRDSE1 ioaddr + 0x34
#define dwNextRDSE2 ioaddr + 0x38
#define dwNextRDSE3 ioaddr + 0x3c
#define dwCurrentTDSE0 ioaddr + 0x40
#define dwCurrentTDSE1 ioaddr + 0x44
#define dwCurrentTDSE2 ioaddr + 0x48
#define dwCurrentTDSE3 ioaddr + 0x4c
#define dwNextTDSE0 ioaddr + 0x50
#define dwNextTDSE1 ioaddr + 0x54
#define dwNextTDSE2 ioaddr + 0x58
#define dwNextTDSE3 ioaddr + 0x5c
#define dwCurrRxDMAPtr ioaddr + 0x60
#define dwCurrTxDMAPtr ioaddr + 0x64
#define byMPHY ioaddr + 0x6c
#define byMIISR ioaddr + 0x6d
#define byBCR0 ioaddr + 0x6e
#define byBCR1 ioaddr + 0x6f
#define byMIICR ioaddr + 0x70
#define byMIIAD ioaddr + 0x71
#define wMIIDATA ioaddr + 0x72
#define byEECSR ioaddr + 0x74
#define byTEST ioaddr + 0x75
#define byGPIO ioaddr + 0x76
#define byCFGA ioaddr + 0x78
#define byCFGB ioaddr + 0x79
#define byCFGC ioaddr + 0x7a
#define byCFGD ioaddr + 0x7b
#define wTallyCntMPA ioaddr + 0x7c
#define wTallyCntCRC ioaddr + 0x7d
/*--------------------- Exioaddr Definitions -------------------------*/
//
// Bits in the RCR register
//
/*
* Bits in the RCR register
*/
#define RCR_RRFT2 0x80 //
#define RCR_RRFT1 0x40 //
#define RCR_RRFT0 0x20 //
#define RCR_PROM 0x10 //
#define RCR_AB 0x08 //
#define RCR_AM 0x04 //
#define RCR_AR 0x02 //
#define RCR_SEP 0x01 //
#define RCR_RRFT2 0x80
#define RCR_RRFT1 0x40
#define RCR_RRFT0 0x20
#define RCR_PROM 0x10
#define RCR_AB 0x08
#define RCR_AM 0x04
#define RCR_AR 0x02
#define RCR_SEP 0x01
//
// Bits in the TCR register
//
/*
* Bits in the TCR register
*/
#define TCR_RTSF 0x80 //
#define TCR_RTFT1 0x40 //
#define TCR_RTFT0 0x20 //
#define TCR_OFSET 0x08 //
#define TCR_LB1 0x04 // loopback[1]
#define TCR_LB0 0x02 // loopback[0]
#define TCR_RTSF 0x80
#define TCR_RTFT1 0x40
#define TCR_RTFT0 0x20
#define TCR_OFSET 0x08
#define TCR_LB1 0x04 /* loopback[1] */
#define TCR_LB0 0x02 /* loopback[0] */
//
// Bits in the CR0 register
//
/*
* Bits in the CR0 register
*/
#define CR0_RDMD 0x40 // rx descriptor polling demand
#define CR0_TDMD 0x20 // tx descriptor polling demand
#define CR0_TXON 0x10 //
#define CR0_RXON 0x08 //
#define CR0_STOP 0x04 // stop NIC, default = 1
#define CR0_STRT 0x02 // start NIC
#define CR0_INIT 0x01 // start init process
#define CR0_RDMD 0x40 /* rx descriptor polling demand */
#define CR0_TDMD 0x20 /* tx descriptor polling demand */
#define CR0_TXON 0x10
#define CR0_RXON 0x08
#define CR0_STOP 0x04 /* stop NIC, default = 1 */
#define CR0_STRT 0x02 /* start NIC */
#define CR0_INIT 0x01 /* start init process */
//
// Bits in the CR1 register
//
/*
* Bits in the CR1 register
*/
#define CR1_SFRST 0x80 // software reset
#define CR1_RDMD1 0x40 // RDMD1
#define CR1_TDMD1 0x20 // TDMD1
#define CR1_KEYPAG 0x10 // turn on par/key
#define CR1_DPOLL 0x08 // disable rx/tx auto polling
#define CR1_FDX 0x04 // full duplex mode
#define CR1_ETEN 0x02 // early tx mode
#define CR1_EREN 0x01 // early rx mode
#define CR1_SFRST 0x80 /* software reset */
#define CR1_RDMD1 0x40 /* RDMD1 */
#define CR1_TDMD1 0x20 /* TDMD1 */
#define CR1_KEYPAG 0x10 /* turn on par/key */
#define CR1_DPOLL 0x08 /* disable rx/tx auto polling */
#define CR1_FDX 0x04 /* full duplex mode */
#define CR1_ETEN 0x02 /* early tx mode */
#define CR1_EREN 0x01 /* early rx mode */
//
// Bits in the CR register
//
/*
* Bits in the CR register
*/
#define CR_RDMD 0x0040 // rx descriptor polling demand
#define CR_TDMD 0x0020 // tx descriptor polling demand
#define CR_TXON 0x0010 //
#define CR_RXON 0x0008 //
#define CR_STOP 0x0004 // stop NIC, default = 1
#define CR_STRT 0x0002 // start NIC
#define CR_INIT 0x0001 // start init process
#define CR_SFRST 0x8000 // software reset
#define CR_RDMD1 0x4000 // RDMD1
#define CR_TDMD1 0x2000 // TDMD1
#define CR_KEYPAG 0x1000 // turn on par/key
#define CR_DPOLL 0x0800 // disable rx/tx auto polling
#define CR_FDX 0x0400 // full duplex mode
#define CR_ETEN 0x0200 // early tx mode
#define CR_EREN 0x0100 // early rx mode
#define CR_RDMD 0x0040 /* rx descriptor polling demand */
#define CR_TDMD 0x0020 /* tx descriptor polling demand */
#define CR_TXON 0x0010
#define CR_RXON 0x0008
#define CR_STOP 0x0004 /* stop NIC, default = 1 */
#define CR_STRT 0x0002 /* start NIC */
#define CR_INIT 0x0001 /* start init process */
#define CR_SFRST 0x8000 /* software reset */
#define CR_RDMD1 0x4000 /* RDMD1 */
#define CR_TDMD1 0x2000 /* TDMD1 */
#define CR_KEYPAG 0x1000 /* turn on par/key */
#define CR_DPOLL 0x0800 /* disable rx/tx auto polling */
#define CR_FDX 0x0400 /* full duplex mode */
#define CR_ETEN 0x0200 /* early tx mode */
#define CR_EREN 0x0100 /* early rx mode */
//
// Bits in the IMR0 register
//
/*
* Bits in the IMR0 register
*/
#define IMR0_CNTM 0x80 //
#define IMR0_BEM 0x40 //
#define IMR0_RUM 0x20 //
#define IMR0_TUM 0x10 //
#define IMR0_TXEM 0x08 //
#define IMR0_RXEM 0x04 //
#define IMR0_PTXM 0x02 //
#define IMR0_PRXM 0x01 //
#define IMR0_CNTM 0x80
#define IMR0_BEM 0x40
#define IMR0_RUM 0x20
#define IMR0_TUM 0x10
#define IMR0_TXEM 0x08
#define IMR0_RXEM 0x04
#define IMR0_PTXM 0x02
#define IMR0_PRXM 0x01
// define imrshadow
/* define imrshadow */
#define IMRShadow 0x5AFF
#define IMRShadow 0x5AFF
//
// Bits in the IMR1 register
//
/*
* Bits in the IMR1 register
*/
#define IMR1_INITM 0x80 //
#define IMR1_SRCM 0x40 //
#define IMR1_NBFM 0x10 //
#define IMR1_PRAIM 0x08 //
#define IMR1_RES0M 0x04 //
#define IMR1_ETM 0x02 //
#define IMR1_ERM 0x01 //
#define IMR1_INITM 0x80
#define IMR1_SRCM 0x40
#define IMR1_NBFM 0x10
#define IMR1_PRAIM 0x08
#define IMR1_RES0M 0x04
#define IMR1_ETM 0x02
#define IMR1_ERM 0x01
//
// Bits in the ISR register
//
/*
* Bits in the ISR register
*/
#define ISR_INITI 0x8000 //
#define ISR_SRCI 0x4000 //
#define ISR_ABTI 0x2000 //
#define ISR_NORBF 0x1000 //
#define ISR_PKTRA 0x0800 //
#define ISR_RES0 0x0400 //
#define ISR_ETI 0x0200 //
#define ISR_ERI 0x0100 //
#define ISR_CNT 0x0080 //
#define ISR_BE 0x0040 //
#define ISR_RU 0x0020 //
#define ISR_TU 0x0010 //
#define ISR_TXE 0x0008 //
#define ISR_RXE 0x0004 //
#define ISR_PTX 0x0002 //
#define ISR_PRX 0x0001 //
#define ISR_INITI 0x8000
#define ISR_SRCI 0x4000
#define ISR_ABTI 0x2000
#define ISR_NORBF 0x1000
#define ISR_PKTRA 0x0800
#define ISR_RES0 0x0400
#define ISR_ETI 0x0200
#define ISR_ERI 0x0100
#define ISR_CNT 0x0080
#define ISR_BE 0x0040
#define ISR_RU 0x0020
#define ISR_TU 0x0010
#define ISR_TXE 0x0008
#define ISR_RXE 0x0004
#define ISR_PTX 0x0002
#define ISR_PRX 0x0001
//
// Bits in the ISR0 register
//
/*
* Bits in the ISR0 register
*/
#define ISR0_CNT 0x80 //
#define ISR0_BE 0x40 //
#define ISR0_RU 0x20 //
#define ISR0_TU 0x10 //
#define ISR0_TXE 0x08 //
#define ISR0_RXE 0x04 //
#define ISR0_PTX 0x02 //
#define ISR0_PRX 0x01 //
#define ISR0_CNT 0x80
#define ISR0_BE 0x40
#define ISR0_RU 0x20
#define ISR0_TU 0x10
#define ISR0_TXE 0x08
#define ISR0_RXE 0x04
#define ISR0_PTX 0x02
#define ISR0_PRX 0x01
//
// Bits in the ISR1 register
//
/*
* Bits in the ISR1 register
*/
#define ISR1_INITI 0x80 //
#define ISR1_SRCI 0x40 //
#define ISR1_NORBF 0x10 //
#define ISR1_PKTRA 0x08 //
#define ISR1_ETI 0x02 //
#define ISR1_ERI 0x01 //
#define ISR1_INITI 0x80
#define ISR1_SRCI 0x40
#define ISR1_NORBF 0x10
#define ISR1_PKTRA 0x08
#define ISR1_ETI 0x02
#define ISR1_ERI 0x01
// ISR ABNORMAL CONDITION
/* ISR ABNORMAL CONDITION */
#define ISR_ABNORMAL ISR_BE+ISR_RU+ISR_TU+ISR_CNT+ISR_NORBF+ISR_PKTRA
//
// Bits in the MIISR register
//
/*
* Bits in the MIISR register
*/
#define MIISR_MIIERR 0x08 //
#define MIISR_MRERR 0x04 //
#define MIISR_LNKFL 0x02 //
#define MIISR_SPEED 0x01 //
#define MIISR_MIIERR 0x08
#define MIISR_MRERR 0x04
#define MIISR_LNKFL 0x02
#define MIISR_SPEED 0x01
//
// Bits in the MIICR register
//
/*
* Bits in the MIICR register
*/
#define MIICR_MAUTO 0x80 //
#define MIICR_RCMD 0x40 //
#define MIICR_WCMD 0x20 //
#define MIICR_MDPM 0x10 //
#define MIICR_MOUT 0x08 //
#define MIICR_MDO 0x04 //
#define MIICR_MDI 0x02 //
#define MIICR_MDC 0x01 //
#define MIICR_MAUTO 0x80
#define MIICR_RCMD 0x40
#define MIICR_WCMD 0x20
#define MIICR_MDPM 0x10
#define MIICR_MOUT 0x08
#define MIICR_MDO 0x04
#define MIICR_MDI 0x02
#define MIICR_MDC 0x01
//
// Bits in the EECSR register
//
/*
* Bits in the EECSR register
*/
#define EECSR_EEPR 0x80 // eeprom programed status, 73h means programed
#define EECSR_EMBP 0x40 // eeprom embeded programming
#define EECSR_AUTOLD 0x20 // eeprom content reload
#define EECSR_DPM 0x10 // eeprom direct programming
#define EECSR_CS 0x08 // eeprom CS pin
#define EECSR_SK 0x04 // eeprom SK pin
#define EECSR_DI 0x02 // eeprom DI pin
#define EECSR_DO 0x01 // eeprom DO pin
#define EECSR_EEPR 0x80 /* eeprom programed status, 73h means programed */
#define EECSR_EMBP 0x40 /* eeprom embeded programming */
#define EECSR_AUTOLD 0x20 /* eeprom content reload */
#define EECSR_DPM 0x10 /* eeprom direct programming */
#define EECSR_CS 0x08 /* eeprom CS pin */
#define EECSR_SK 0x04 /* eeprom SK pin */
#define EECSR_DI 0x02 /* eeprom DI pin */
#define EECSR_DO 0x01 /* eeprom DO pin */
//
// Bits in the BCR0 register
//
/*
* Bits in the BCR0 register
*/
#define BCR0_CRFT2 0x20 //
#define BCR0_CRFT1 0x10 //
#define BCR0_CRFT0 0x08 //
#define BCR0_DMAL2 0x04 //
#define BCR0_DMAL1 0x02 //
#define BCR0_DMAL0 0x01 //
#define BCR0_CRFT2 0x20
#define BCR0_CRFT1 0x10
#define BCR0_CRFT0 0x08
#define BCR0_DMAL2 0x04
#define BCR0_DMAL1 0x02
#define BCR0_DMAL0 0x01
//
// Bits in the BCR1 register
//
/*
* Bits in the BCR1 register
*/
#define BCR1_CTSF 0x20 //
#define BCR1_CTFT1 0x10 //
#define BCR1_CTFT0 0x08 //
#define BCR1_POT2 0x04 //
#define BCR1_POT1 0x02 //
#define BCR1_POT0 0x01 //
#define BCR1_CTSF 0x20
#define BCR1_CTFT1 0x10
#define BCR1_CTFT0 0x08
#define BCR1_POT2 0x04
#define BCR1_POT1 0x02
#define BCR1_POT0 0x01
//
// Bits in the CFGA register
//
/*
* Bits in the CFGA register
*/
#define CFGA_EELOAD 0x80 // enable eeprom embeded and direct programming
#define CFGA_JUMPER 0x40 //
#define CFGA_MTGPIO 0x08 //
#define CFGA_T10EN 0x02 //
#define CFGA_AUTO 0x01 //
#define CFGA_EELOAD 0x80 /* enable eeprom embeded and direct programming */
#define CFGA_JUMPER 0x40
#define CFGA_MTGPIO 0x08
#define CFGA_T10EN 0x02
#define CFGA_AUTO 0x01
//
// Bits in the CFGB register
//
/*
* Bits in the CFGB register
*/
#define CFGB_PD 0x80 //
#define CFGB_POLEN 0x02 //
#define CFGB_LNKEN 0x01 //
#define CFGB_PD 0x80
#define CFGB_POLEN 0x02
#define CFGB_LNKEN 0x01
//
// Bits in the CFGC register
//
/*
* Bits in the CFGC register
*/
#define CFGC_M10TIO 0x80 //
#define CFGC_M10POL 0x40 //
#define CFGC_PHY1 0x20 //
#define CFGC_PHY0 0x10 //
#define CFGC_BTSEL 0x08 //
#define CFGC_BPS2 0x04 // bootrom select[2]
#define CFGC_BPS1 0x02 // bootrom select[1]
#define CFGC_BPS0 0x01 // bootrom select[0]
#define CFGC_M10TIO 0x80
#define CFGC_M10POL 0x40
#define CFGC_PHY1 0x20
#define CFGC_PHY0 0x10
#define CFGC_BTSEL 0x08
#define CFGC_BPS2 0x04 /* bootrom select[2] */
#define CFGC_BPS1 0x02 /* bootrom select[1] */
#define CFGC_BPS0 0x01 /* bootrom select[0] */
//
// Bits in the CFGD register
//
/*
* Bits in the CFGD register
*/
#define CFGD_GPIOEN 0x80 //
#define CFGD_DIAG 0x40 //
#define CFGD_MAGIC 0x10 //
#define CFGD_CFDX 0x04 //
#define CFGD_CEREN 0x02 //
#define CFGD_CETEN 0x01 //
#define CFGD_GPIOEN 0x80
#define CFGD_DIAG 0x40
#define CFGD_MAGIC 0x10
#define CFGD_CFDX 0x04
#define CFGD_CEREN 0x02
#define CFGD_CETEN 0x01
// Bits in RSR
#define RSR_RERR 0x00000001
#define RSR_CRC 0x00000002
#define RSR_FAE 0x00000004
#define RSR_FOV 0x00000008
#define RSR_LONG 0x00000010
#define RSR_RUNT 0x00000020
#define RSR_SERR 0x00000040
#define RSR_BUFF 0x00000080
#define RSR_EDP 0x00000100
#define RSR_STP 0x00000200
#define RSR_CHN 0x00000400
#define RSR_PHY 0x00000800
#define RSR_BAR 0x00001000
#define RSR_MAR 0x00002000
#define RSR_RXOK 0x00008000
#define RSR_ABNORMAL RSR_RERR+RSR_LONG+RSR_RUNT
/* Bits in RSR */
#define RSR_RERR 0x00000001
#define RSR_CRC 0x00000002
#define RSR_FAE 0x00000004
#define RSR_FOV 0x00000008
#define RSR_LONG 0x00000010
#define RSR_RUNT 0x00000020
#define RSR_SERR 0x00000040
#define RSR_BUFF 0x00000080
#define RSR_EDP 0x00000100
#define RSR_STP 0x00000200
#define RSR_CHN 0x00000400
#define RSR_PHY 0x00000800
#define RSR_BAR 0x00001000
#define RSR_MAR 0x00002000
#define RSR_RXOK 0x00008000
#define RSR_ABNORMAL RSR_RERR+RSR_LONG+RSR_RUNT
//Bits in TSR
#define TSR_NCR0 0x00000001
#define TSR_NCR1 0x00000002
#define TSR_NCR2 0x00000004
#define TSR_NCR3 0x00000008
#define TSR_COLS 0x00000010
#define TSR_CDH 0x00000080
#define TSR_ABT 0x00000100
#define TSR_OWC 0x00000200
#define TSR_CRS 0x00000400
#define TSR_UDF 0x00000800
#define TSR_TBUFF 0x00001000
#define TSR_SERR 0x00002000
#define TSR_JAB 0x00004000
#define TSR_TERR 0x00008000
#define TSR_ABNORMAL TSR_TERR+TSR_OWC+TSR_ABT+TSR_JAB+TSR_CRS
#define TSR_OWN_BIT 0x80000000
/* Bits in TSR */
#define TSR_NCR0 0x00000001
#define TSR_NCR1 0x00000002
#define TSR_NCR2 0x00000004
#define TSR_NCR3 0x00000008
#define TSR_COLS 0x00000010
#define TSR_CDH 0x00000080
#define TSR_ABT 0x00000100
#define TSR_OWC 0x00000200
#define TSR_CRS 0x00000400
#define TSR_UDF 0x00000800
#define TSR_TBUFF 0x00001000
#define TSR_SERR 0x00002000
#define TSR_JAB 0x00004000
#define TSR_TERR 0x00008000
#define TSR_ABNORMAL TSR_TERR+TSR_OWC+TSR_ABT+TSR_JAB+TSR_CRS
#define TSR_OWN_BIT 0x80000000
#define CB_DELAY_LOOP_WAIT (10) // 10ms
// enabled mask value of irq
#define CB_DELAY_LOOP_WAIT 10 /* 10ms */
/* enabled mask value of irq */
#define W_IMR_MASK_VALUE 0x1BFF // initial value of IMR
#define W_IMR_MASK_VALUE 0x1BFF /* initial value of IMR */
// Ethernet address filter type
#define PKT_TYPE_DIRECTED 0x0001 // obselete, directed address is always accepted
#define PKT_TYPE_MULTICAST 0x0002
#define PKT_TYPE_ALL_MULTICAST 0x0004
#define PKT_TYPE_BROADCAST 0x0008
#define PKT_TYPE_PROMISCUOUS 0x0020
//#define PKT_TYPE_LONG 0x2000
#define PKT_TYPE_RUNT 0x4000
#define PKT_TYPE_ERROR 0x8000 // accept error packets, e.g. CRC error
/* Ethernet address filter type */
#define PKT_TYPE_DIRECTED 0x0001 /* obsolete, directed address is always accepted */
#define PKT_TYPE_MULTICAST 0x0002
#define PKT_TYPE_ALL_MULTICAST 0x0004
#define PKT_TYPE_BROADCAST 0x0008
#define PKT_TYPE_PROMISCUOUS 0x0020
#define PKT_TYPE_LONG 0x2000
#define PKT_TYPE_RUNT 0x4000
#define PKT_TYPE_ERROR 0x8000 /* accept error packets, e.g. CRC error */
// Loopback mode
/* Loopback mode */
#define NIC_LB_NONE 0x00 //
#define NIC_LB_INTERNAL 0x01 //
#define NIC_LB_PHY 0x02 // MII or Internal-10BaseT loopback
#define NIC_LB_NONE 0x00
#define NIC_LB_INTERNAL 0x01
#define NIC_LB_PHY 0x02 /* MII or Internal-10BaseT loopback */
#define TX_RING_SIZE 2
#define RX_RING_SIZE 2
#define TX_RING_SIZE 2
#define RX_RING_SIZE 2
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */
/* Transmit and receive descriptors definition */
@ -522,7 +521,7 @@ struct rhine_rx_desc
/* The I/O extent. */
#define rhine_TOTAL_SIZE 0x80
#ifdef HAVE_DEVLIST
#ifdef HAVE_DEVLIST
struct netdev_entry rhine_drv =
{ "rhine", rhine_probe, rhine_TOTAL_SIZE, NULL };
#endif
@ -619,7 +618,7 @@ The chip does not pad to minimum transmit length.
*/
#define PCI_VENDOR_ID_FET 0x1106
#define PCI_DEVICE_ID_FET_3043 0x3043
#define PCI_DEVICE_ID_FET_3043 0x3043
/* The rest of these values should never change. */
#define NUM_TX_DESC 2 /* Number of Tx descriptor registers. */
@ -659,14 +658,16 @@ static int QueryAuto (int);
static int ReadMII (int byMIIIndex, int);
static void WriteMII (char, char, char, int);
static void MIIDelay (void);
static void post_reset_delay (void);
static unsigned int read_tick_counter (void);
static void rhine_init_ring (struct nic *dev);
static void rhine_disable (struct nic *nic);
static void rhine_reset (struct nic *nic);
static int rhine_poll (struct nic *nic);
static void rhine_transmit (struct nic *nic, char *d, unsigned int t,
unsigned int s, char *p);
static void rhine_transmit (struct nic *nic, const char *d, unsigned int t,
unsigned int s, const char *p);
/* Linux support functions */
#define virt_to_bus(x) ((unsigned long)x)
#define bus_to_virt(x) ((void *)x)
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void
@ -687,12 +688,12 @@ rhine_init_ring (struct nic *nic)
tp->rx_ring[i].buf_addr_1 = virt_to_bus (tp->rx_buffs[i]);
tp->rx_ring[i].buf_addr_2 = virt_to_bus (&tp->rx_ring[i + 1]);
// printf("[%d]buf1=%x,buf2=%x",i,tp->rx_ring[i].buf_addr_1,tp->rx_ring[i].buf_addr_2);
/* printf("[%d]buf1=%x,buf2=%x",i,tp->rx_ring[i].buf_addr_1,tp->rx_ring[i].buf_addr_2); */
}
/* Mark the last entry as wrapping the ring. */
// tp->rx_ring[i-1].rx_ctrl.bits.rx_buf_size =1518;
/* tp->rx_ring[i-1].rx_ctrl.bits.rx_buf_size =1518; */
tp->rx_ring[i - 1].buf_addr_2 = virt_to_bus (&tp->rx_ring[0]);
//printf("[%d]buf1=%x,buf2=%x",i-1,tp->rx_ring[i-1].buf_addr_1,tp->rx_ring[i-1].buf_addr_2);
/*printf("[%d]buf1=%x,buf2=%x",i-1,tp->rx_ring[i-1].buf_addr_1,tp->rx_ring[i-1].buf_addr_2); */
/* The Tx buffer descriptor is filled in as needed, but we
do need to clear the ownership bit. */
@ -704,11 +705,11 @@ rhine_init_ring (struct nic *nic)
tp->tx_ring[i].tx_ctrl.lw = 0x00e08000;
tp->tx_ring[i].buf_addr_1 = virt_to_bus (tp->tx_buffs[i]);
tp->tx_ring[i].buf_addr_2 = virt_to_bus (&tp->tx_ring[i + 1]);
// printf("[%d]buf1=%x,buf2=%x",i,tp->tx_ring[i].buf_addr_1,tp->tx_ring[i].buf_addr_2);
/* printf("[%d]buf1=%x,buf2=%x",i,tp->tx_ring[i].buf_addr_1,tp->tx_ring[i].buf_addr_2); */
}
tp->tx_ring[i - 1].buf_addr_2 = virt_to_bus (&tp->tx_ring[0]);
// printf("[%d]buf1=%x,buf2=%x",i,tp->tx_ring[i-1].buf_addr_1,tp->tx_ring[i-1].buf_addr_2);
/* printf("[%d]buf1=%x,buf2=%x",i,tp->tx_ring[i-1].buf_addr_1,tp->tx_ring[i-1].buf_addr_2); */
}
int
@ -862,44 +863,6 @@ MIIDelay (void)
}
}
static unsigned int
read_tick_counter (void)
{
unsigned int current_time = 0;
/* Program 8254 to latch T0's count */
outb (0x43, 0x6);
/* Read the counter */
current_time = inb (0x40);
current_time = current_time | (inb (0x40) << 8);
return current_time;
}
static void
post_reset_delay (void)
{
unsigned int initial_time, current_time;
/* need to wait 10 mini seconds */
initial_time = read_tick_counter ();
/* 8254 time tick gives 419 nsec per count. We have to delay a delta
count of 10,000,000ns/419ns = 23866. We will round it up to 23866
*/
while (1)
{
current_time = read_tick_counter ();
if ((initial_time - current_time) >= 23866)
{ /* 10 mini second */
return;
}
}
}
struct nic *
rhine_probe (struct nic *nic, unsigned short *probeaddrs,
struct pci_device *pci)
@ -947,7 +910,8 @@ rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
{
struct rhine_private *tp;
static int did_version = 0; /* Already printed version info. */
int i, x;
int i;
unsigned int timeout;
int FDXFlag;
int byMIIvalue, LineSpeed, MIICRbak;
@ -967,8 +931,10 @@ rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
printf ("Analyzing Media type,this will take several seconds........");
for (i = 0; i < 5; i++)
{
for (x = 0; x < 100; x++)
post_reset_delay ();
/* need to wait 1 millisecond - we will round it up to 50-100ms */
timeout = currticks() + 2;
for (timeout = currticks() + 2; currticks() < timeout;)
/* nothing */;
if (ReadMII (1, ioaddr) & 0x0020)
break;
}
@ -1005,8 +971,7 @@ rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
outb (0x41, byMIIAD);
MIIDelay ();
// while((inb(byMIIAD)&0x20)==0)
// ;
/* while((inb(byMIIAD)&0x20)==0) ; */
outb (MIICRbak | 0x80, byMIICR);
nic->priv_data = &rhine;
@ -1048,14 +1013,21 @@ rhine_reset (struct nic *nic)
int rx_bufs_tmp, rx_bufs_tmp1;
int tx_bufs_tmp, tx_bufs_tmp1;
#ifndef USE_INTERNAL_BUFFER
#define buf1 (0x10000 - (RX_RING_SIZE * PKT_BUF_SZ + 32))
#define buf2 (buf1 - (RX_RING_SIZE * PKT_BUF_SZ + 32))
#define desc1 (buf2 - (TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32))
#define desc2 (desc1 - (TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32))
#else
static char buf1[RX_RING_SIZE * PKT_BUF_SZ + 32];
static char buf2[RX_RING_SIZE * PKT_BUF_SZ + 32];
static char desc1[TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32];
static char desc2[TX_RING_SIZE * sizeof (struct rhine_tx_desc) + 32];
#endif
// printf ("rhine_reset\n");
/* printf ("rhine_reset\n"); */
/* Soft reset the chip. */
//outb(CmdReset, ioaddr + ChipCmd);
/*outb(CmdReset, ioaddr + ChipCmd); */
tx_bufs_tmp = (int) buf1;
tx_ring_tmp = (int) desc1;
@ -1065,40 +1037,40 @@ rhine_reset (struct nic *nic)
/* tune RD TD 32 byte alignment */
rx_ring_tmp1 = (int) virt_to_bus ((char *) rx_ring_tmp);
j = (rx_ring_tmp1 + 32) & (~0x1f);
// printf ("txring[%d]", j);
/* printf ("txring[%d]", j); */
tp->rx_ring = (struct rhine_rx_desc *) bus_to_virt (j);
tx_ring_tmp1 = (int) virt_to_bus ((char *) tx_ring_tmp);
j = (tx_ring_tmp1 + 32) & (~0x1f);
tp->tx_ring = (struct rhine_tx_desc *) bus_to_virt (j);
// printf ("rxring[%x]", j);
/* printf ("rxring[%x]", j); */
tx_bufs_tmp1 = (int) virt_to_bus ((char *) tx_bufs_tmp);
j = (int) (tx_bufs_tmp1 + 32) & (~0x1f);
tx_bufs_tmp = (int) bus_to_virt (j);
// printf ("txb[%x]", j);
/* printf ("txb[%x]", j); */
rx_bufs_tmp1 = (int) virt_to_bus ((char *) rx_bufs_tmp);
j = (int) (rx_bufs_tmp1 + 32) & (~0x1f);
rx_bufs_tmp = (int) bus_to_virt (j);
// printf ("rxb[%x][%x]", rx_bufs_tmp1, j);
/* printf ("rxb[%x][%x]", rx_bufs_tmp1, j); */
for (i = 0; i < RX_RING_SIZE; i++)
{
tp->rx_buffs[i] = (char *) rx_bufs_tmp;
// printf("r[%x]",tp->rx_buffs[i]);
/* printf("r[%x]",tp->rx_buffs[i]); */
rx_bufs_tmp += 1536;
}
for (i = 0; i < TX_RING_SIZE; i++)
{
tp->tx_buffs[i] = (char *) tx_bufs_tmp;
// printf("t[%x]",tp->tx_buffs[i]);
/* printf("t[%x]",tp->tx_buffs[i]); */
tx_bufs_tmp += 1536;
}
// printf ("init ring");
/* printf ("init ring"); */
rhine_init_ring (nic);
/*write TD RD Descriptor to MAC */
outl (virt_to_bus (tp->rx_ring), dwCurrentRxDescAddr);
@ -1123,9 +1095,9 @@ rhine_reset (struct nic *nic)
outw (CR_FDX, byCR0);
}
/*KICK NIC to WORK */
/* KICK NIC to WORK */
CRbak = inw (byCR0);
CRbak = CRbak & 0xFFFB; /*not CR_STOP */
CRbak = CRbak & 0xFFFB; /* not CR_STOP */
outw ((CRbak | CR_STRT | CR_TXON | CR_RXON | CR_DPOLL), byCR0);
/*set IMR to work */
@ -1136,7 +1108,6 @@ static int
rhine_poll (struct nic *nic)
{
struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
int ioaddr = tp->ioaddr;
int rxstatus, good = 0;;
if (tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit == 0)
@ -1157,7 +1128,7 @@ rhine_poll (struct nic *nic)
{
nic->packetlen = tp->rx_ring[tp->cur_rx].rx_status.bits.frame_length;
memcpy (nic->packet, tp->rx_buffs[tp->cur_rx], nic->packetlen);
// printf ("Packet RXed\n");
/* printf ("Packet RXed\n"); */
}
tp->rx_ring[tp->cur_rx].rx_status.bits.own_bit = 1;
tp->cur_rx++;
@ -1168,14 +1139,14 @@ rhine_poll (struct nic *nic)
static void
rhine_transmit (struct nic *nic,
char *d, unsigned int t, unsigned int s, char *p)
const char *d, unsigned int t, unsigned int s, const char *p)
{
struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
int ioaddr = tp->ioaddr;
int entry;
unsigned char CR1bak;
//printf ("rhine_transmit\n");
/*printf ("rhine_transmit\n"); */
/* setup ethernet header */
@ -1199,21 +1170,21 @@ rhine_transmit (struct nic *nic,
CR1bak = inb (byCR1);
CR1bak = CR1bak | CR1_TDMD1;
//printf("tdsw=[%x]",tp->tx_ring[entry].tx_status.lw);
//printf("tdcw=[%x]",tp->tx_ring[entry].tx_ctrl.lw);
//printf("tdbuf1=[%x]",tp->tx_ring[entry].buf_addr_1);
//printf("tdbuf2=[%x]",tp->tx_ring[entry].buf_addr_2);
//printf("td1=[%x]",inl(dwCurrentTDSE0));
//printf("td2=[%x]",inl(dwCurrentTDSE1));
//printf("td3=[%x]",inl(dwCurrentTDSE2));
//printf("td4=[%x]",inl(dwCurrentTDSE3));
/*printf("tdsw=[%x]",tp->tx_ring[entry].tx_status.lw); */
/*printf("tdcw=[%x]",tp->tx_ring[entry].tx_ctrl.lw); */
/*printf("tdbuf1=[%x]",tp->tx_ring[entry].buf_addr_1); */
/*printf("tdbuf2=[%x]",tp->tx_ring[entry].buf_addr_2); */
/*printf("td1=[%x]",inl(dwCurrentTDSE0)); */
/*printf("td2=[%x]",inl(dwCurrentTDSE1)); */
/*printf("td3=[%x]",inl(dwCurrentTDSE2)); */
/*printf("td4=[%x]",inl(dwCurrentTDSE3)); */
outb (CR1bak, byCR1);
tp->cur_tx++;
//outw(IMRShadow,byIMR0);
//dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE);
//tp->tx_skbuff[entry] = 0;
/*outw(IMRShadow,byIMR0); */
/*dev_kfree_skb(tp->tx_skbuff[entry], FREE_WRITE); */
/*tp->tx_skbuff[entry] = 0; */
}
// EOF via-rhine.c
/* EOF via-rhine.c */