2002-01-03 Yoshinori K. Okuji <okuji@gnu.org>

Update the netboot stuff to Etherboot-5.0.5.

	* configure.in (--enable-3c590): Removed. This was a mistake.
	(--enable-davicom): New option.
	(--enable-eepro): Likewise.
	(--enable-natsemi): Likewise.
	(--enable-ni5010): Likewise.
	(--enable-sis900): Likewise.
	(--enable-w89c840): Likewise.
	(--enable-3c509-hack): Removed.
	(--enable-ns8390-force-16bit): Likewise.

	* netboot/Makefile.am (libdrivers_a_SOURCES): Added timer.c and
	timer.h.
	(EXTRA_libdrivers_a_SOURCES): Added davicom.c, eepro.c, fa311.c,
	natsemi.c, ni5010.c, sis900.c, sis900.h, tlan.c and w89c840.c.
	(EXTRA_DIST): Added sis900.txt.
	(3c595_drivers): Remove 3c590.o from this.
	(davicom_drivers): New variable.
	(eepro_drivers): Likewise.
	(natsemi_drivers): Likewise.
	(ni5010_drivers): Likewise.
	(sis900_drivers): Likewise.
	(w89c840_drivers): Likewise.
	(3c590_o_CFLAGS): Removed.
	(davicom_o_CFLAGS): New variable.
	(eepro_o_CFLAGS): Likewise.
	(natsemi_o_CFLAGS): Likewise.
	(ni5010_o_CFLAGS): Likewise.
	(sis900_o_CFLAGS): Likewise.
	(w89c840_o_CFLAGS): Likewise.

	* netboot/davicom.c: New file, from Etherboot-5.0.5.
	* netboot/eepro.c: Likewise.
	* netboot/natsemi.c: Likewise.
	* netboot/ni5010.c: Likewise.
	* netboot/sis900.c: Likewise.
	* netboot/sis900.h: Likewise.
	* netboot/sis900.txt: Likewise.
	* netboot/timer.c: Likewise.
	* netboot/timer.h: Likewise.
	* netboot/w89c840.c: Likewise.
	* netboot/fa311.c: Likewise.
	* netboot/tlan.c: Likewise.

	* netboot/3c509.c: Copied from Etherboot-5.0.5.
	* netboot/3c509.h: Likewise.
	* netboot/3c595.c: Likewise.
	* netboot/3c90x.c: Likewise.
	* netboot/3c90x.txt: Likewise.
	* netboot/cards.h: Likewise.
	* netboot/cs89x0.c: Likewise.
	* netboot/depca.c: Likewise.
	* netboot/eepro100.c: Likewise.
	* netboot/epic100.c: Likewise.
	* netboot/i82586.c: Likewise.
	* netboot/lance.c: Likewise.
	* netboot/linux-asm-string.h: Likewise.
	* netboot/nic.h: Likewise.
	* netboot/ns8390.c: Likewise.
	* netboot/ns8390.h: Likewise.
	* netboot/otulip.c: Likewise.
	* netboot/pci.h: Likewise.
	* netboot/rtl8139.c: Likewise.
	* netboot/sk_g16.c: Likewise.
	* netboot/smc9000.c: Likewise.
	* netboot/tiara.c: Likewise.
	* netboot/tulip.c: Likewise.
	* netboot/via-rhine.c: Likewise.

	* netboot/config.c: Applied a diff between Etherboot-4.6.18 and
	Etherboot-5.0.5 manually.
	* netboot/main.c: Likewise.
	* netboot/pci.c: Likewise.
	* netboot/etherboot.h: Rewritten mostly from scratch, based on
	the same file in Etherboot-5.0.5.
	* netboot/misc.c: Likewise.
	* netboot/osdep.h: Likewise.
	* netboot/fsys_tftp.c (GRUB): Defined.
	(buf_fill): Use rfc2131_sleep_interval instead of rfc951_sleep.

	* stage2/builtins.c [SUPPORT_NETBOOT] (GRUB): Defined.
	(boot_func) [SUPPORT_NETBOOT]: Call cleanup_net.
	* stage2/cmdline.c [SUPPORT_DISKLESS] (GRUB): Defined.
	* stage2/common.c [SUPPORT_DISKLESS] (GRUB): Likewise.
This commit is contained in:
okuji 2002-01-02 21:56:40 +00:00
parent daa965eccc
commit 973e6f4129
54 changed files with 13400 additions and 3545 deletions

5
BUGS
View file

@ -1,5 +1,10 @@
Known problems/bugs:
- In the netboot code, tlan and fa311 are not used, even though they
are distributed. That's because the entry for tlan is commented out
in the file "NIC" of Etherboot, and fa311 isn't used actually in
Etherboot. Probably they will be fixed in next version of Etherboot.
- The command "geometry" doesn't work with a floppy very well. This
bug was incorporated after the rewrite of the partition scanning
code by okuji.

View file

@ -1,3 +1,91 @@
2002-01-03 Yoshinori K. Okuji <okuji@gnu.org>
Update the netboot stuff to Etherboot-5.0.5.
* configure.in (--enable-3c590): Removed. This was a mistake.
(--enable-davicom): New option.
(--enable-eepro): Likewise.
(--enable-natsemi): Likewise.
(--enable-ni5010): Likewise.
(--enable-sis900): Likewise.
(--enable-w89c840): Likewise.
(--enable-3c509-hack): Removed.
(--enable-ns8390-force-16bit): Likewise.
* netboot/Makefile.am (libdrivers_a_SOURCES): Added timer.c and
timer.h.
(EXTRA_libdrivers_a_SOURCES): Added davicom.c, eepro.c, fa311.c,
natsemi.c, ni5010.c, sis900.c, sis900.h, tlan.c and w89c840.c.
(EXTRA_DIST): Added sis900.txt.
(3c595_drivers): Remove 3c590.o from this.
(davicom_drivers): New variable.
(eepro_drivers): Likewise.
(natsemi_drivers): Likewise.
(ni5010_drivers): Likewise.
(sis900_drivers): Likewise.
(w89c840_drivers): Likewise.
(3c590_o_CFLAGS): Removed.
(davicom_o_CFLAGS): New variable.
(eepro_o_CFLAGS): Likewise.
(natsemi_o_CFLAGS): Likewise.
(ni5010_o_CFLAGS): Likewise.
(sis900_o_CFLAGS): Likewise.
(w89c840_o_CFLAGS): Likewise.
* netboot/davicom.c: New file, from Etherboot-5.0.5.
* netboot/eepro.c: Likewise.
* netboot/natsemi.c: Likewise.
* netboot/ni5010.c: Likewise.
* netboot/sis900.c: Likewise.
* netboot/sis900.h: Likewise.
* netboot/sis900.txt: Likewise.
* netboot/timer.c: Likewise.
* netboot/timer.h: Likewise.
* netboot/w89c840.c: Likewise.
* netboot/fa311.c: Likewise.
* netboot/tlan.c: Likewise.
* netboot/3c509.c: Copied from Etherboot-5.0.5.
* netboot/3c509.h: Likewise.
* netboot/3c595.c: Likewise.
* netboot/3c90x.c: Likewise.
* netboot/3c90x.txt: Likewise.
* netboot/cards.h: Likewise.
* netboot/cs89x0.c: Likewise.
* netboot/depca.c: Likewise.
* netboot/eepro100.c: Likewise.
* netboot/epic100.c: Likewise.
* netboot/i82586.c: Likewise.
* netboot/lance.c: Likewise.
* netboot/linux-asm-string.h: Likewise.
* netboot/nic.h: Likewise.
* netboot/ns8390.c: Likewise.
* netboot/ns8390.h: Likewise.
* netboot/otulip.c: Likewise.
* netboot/pci.h: Likewise.
* netboot/rtl8139.c: Likewise.
* netboot/sk_g16.c: Likewise.
* netboot/smc9000.c: Likewise.
* netboot/tiara.c: Likewise.
* netboot/tulip.c: Likewise.
* netboot/via-rhine.c: Likewise.
* netboot/config.c: Applied a diff between Etherboot-4.6.18 and
Etherboot-5.0.5 manually.
* netboot/main.c: Likewise.
* netboot/pci.c: Likewise.
* netboot/etherboot.h: Rewritten mostly from scratch, based on
the same file in Etherboot-5.0.5.
* netboot/misc.c: Likewise.
* netboot/osdep.h: Likewise.
* netboot/fsys_tftp.c (GRUB): Defined.
(buf_fill): Use rfc2131_sleep_interval instead of rfc951_sleep.
* stage2/builtins.c [SUPPORT_NETBOOT] (GRUB): Defined.
(boot_func) [SUPPORT_NETBOOT]: Call cleanup_net.
* stage2/cmdline.c [SUPPORT_DISKLESS] (GRUB): Defined.
* stage2/common.c [SUPPORT_DISKLESS] (GRUB): Likewise.
2002-01-02 Jeremy Katz <katzj@redhat.com>
* util/grub-install.in: Support using mktemp as well as tempfile

748
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -292,13 +292,6 @@ if test "x$enable_3c529" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS 3c529.o"
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
@ -320,6 +313,13 @@ if test "x$enable_cs89x0" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS cs89x0.o"
fi
AC_ARG_ENABLE(davicom,
[ --enable-davicom enable Davicom driver])
if test "x$enable_davicom" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_DAVICOM=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS davicom.o"
fi
AC_ARG_ENABLE(depca,
[ --enable-depca enable DEPCA and EtherWORKS driver])
if test "x$enable_depca" = xyes; then
@ -327,6 +327,13 @@ if test "x$enable_depca" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS depca.o"
fi
AC_ARG_ENABLE(eepro,
[ --enable-eepro enable Etherexpress Pro/10 driver])
if test "x$enable_eepro" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_EEPRO=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS eepro.o"
fi
AC_ARG_ENABLE(eepro100,
[ --enable-eepro100 enable Etherexpress Pro/100 driver])
if test "x$enable_eepro100" = xyes; then
@ -383,6 +390,20 @@ if test "x$enable_ni6510" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ni6510.o"
fi
AC_ARG_ENABLE(natsemi,
[ --enable-natsemi enable NatSemi DP8381x driver])
if test "x$enable_natsemi" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NATSEMI=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS natsemi.o"
fi
AC_ARG_ENABLE(ni5010,
[ --enable-ni5010 enable Racal-Interlan NI5010 driver])
if test "x$enable_ni5010" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_NI5010=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS ni5010.o"
fi
AC_ARG_ENABLE(3c503,
[ --enable-3c503 enable 3Com503 driver])
if test "x$enable_3c503" = xyes; then
@ -425,6 +446,13 @@ if test "x$enable_rtl8139" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS rtl8139.o"
fi
AC_ARG_ENABLE(sis900,
[ --enable-sis900 enable SIS 900 and SIS 7016 driver])
if test "x$enable_sis900" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_SIS900=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS sis900.o"
fi
AC_ARG_ENABLE(sk-g16,
[ --enable-sk-g16 enable Schneider and Koch G16 driver])
if test "x$enable_sk_g16" = xyes; then
@ -460,6 +488,13 @@ if test "x$enable_via_rhine" = xyes; then
NETBOOT_DRIVERS="$NETBOOT_DRIVERS via_rhine.o"
fi
AC_ARG_ENABLE(w89c840,
[ --enable-w89c840 enable Winbond W89c840, Compex RL100-ATX driver])
if test "x$enable_w89c840" = xyes; then
NET_CFLAGS="$NET_CFLAGS -DINCLUDE_W89C840=1"
NETBOOT_DRIVERS="$NETBOOT_DRIVERS w89c840.o"
fi
dnl Check if the netboot support is turned on.
AM_CONDITIONAL(NETBOOT_SUPPORT, test "x$NET_CFLAGS" != x)
if test "x$NET_CFLAGS" != x; then
@ -479,12 +514,6 @@ if test "x$enable_3c503_aui" = xyes; then
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DT503_AUI=1"
fi
AC_ARG_ENABLE(3c509-hack,
[ --enable-3c509-hack make a 3c509 do bootp quicker])
if test "x$enable_3c509_hack" = xyes; then
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DT509HACK=1"
fi
AC_ARG_ENABLE(compex-rl2000-fix,
[ --enable-compex-rl2000-fix
specify this if you have a Compex RL2000 PCI])
@ -492,13 +521,6 @@ if test "x$enable_compex_rl2000_fix" = xyes; then
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DCOMPEX_RL2000_FIX=1"
fi
AC_ARG_ENABLE(ns8390-force-16bit,
[ --enable-ns8390-force-16bit
specify this if falsely 8 bit is detected])
if test "x$enable_ns8390_force_16bit" = xyes; then
NET_EXTRAFLAGS="$NET_EXTRAFLAGS -DNS8390_FORCE_16BIT=1"
fi
AC_ARG_ENABLE(smc9000-scan,
[ --enable-smc9000-scan=LIST
probe for SMC9000 I/O addresses using LIST],

View file

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
.TH GRUB-MD5-CRYPT "8" "December 2001" "grub-md5-crypt (GNU GRUB )" FSF
.TH GRUB-MD5-CRYPT "8" "January 2002" "grub-md5-crypt (GNU GRUB )" FSF
.SH NAME
grub-md5-crypt \- Encrypt a password in MD5 format
.SH SYNOPSIS

View file

@ -1,5 +1,5 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.23.
.TH MBCHK "1" "December 2001" "mbchk (GNU GRUB 0.90)" FSF
.TH MBCHK "1" "January 2002" "mbchk (GNU GRUB 0.90)" FSF
.SH NAME
mbchk \- check the format of a Multiboot kernel
.SH SYNOPSIS

View file

@ -27,11 +27,13 @@ $Id$
#include "etherboot.h"
#include "nic.h"
#include "cards.h"
#include "timer.h"
#include "3c509.h"
static unsigned char eth_vendor, eth_flags, eth_laar;
static unsigned short eth_nic_base, eth_asic_base;
static char bnc=0, utp=0; /* for 3C509 */
#define udelay(n) waiton_timer2(((n)*TICKS_PER_MS)/1000)
static unsigned short eth_nic_base;
static enum { none, bnc, utp } connector = none; /* for 3C509 */
#ifdef INCLUDE_3C529
/*
@ -55,17 +57,6 @@ static struct el3_mca_adapters_struct el3_mca_adapters[] = {
};
#endif
/* a surrogate */
static void DELAY(int val)
{
int c;
for(c=0; c<val; c+=20) {
twiddle();
}
}
/**************************************************************************
ETH_RESET - Reset adapter
***************************************************************************/
@ -77,15 +68,14 @@ static void t509_reset(struct nic *nic)
Reset 3Com 509 card
*************************************************************/
if (eth_vendor != VENDOR_3C509)
return;
/* stop card */
outw(RX_DISABLE, BASE + EP_COMMAND);
outw(RX_DISCARD_TOP_PACK, BASE + EP_COMMAND);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
;
outw(TX_DISABLE, BASE + EP_COMMAND);
outw(STOP_TRANSCEIVER, BASE + EP_COMMAND);
udelay(1000);
outw(RX_RESET, BASE + EP_COMMAND);
outw(TX_RESET, BASE + EP_COMMAND);
outw(C_INTR_LATCH, BASE + EP_COMMAND);
@ -96,7 +86,8 @@ static void t509_reset(struct nic *nic)
/*
* initialize card
*/
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
;
GO_WINDOW(0);
@ -112,7 +103,7 @@ static void t509_reset(struct nic *nic)
GO_WINDOW(2);
/* Reload the ether_addr. */
for (i = 0; i < ETHER_ADDR_SIZE; i++)
for (i = 0; i < ETH_ALEN; i++)
outb(nic->node_addr[i], BASE + EP_W2_ADDR_0 + i);
outw(RX_RESET, BASE + EP_COMMAND);
@ -133,24 +124,24 @@ static void t509_reset(struct nic *nic)
outw(SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST, BASE + EP_COMMAND);
/* configure BNC */
if (bnc) {
if (connector == bnc) {
outw(START_TRANSCEIVER, BASE + EP_COMMAND);
DELAY(10000);
}
udelay(1000);
}
/* configure UTP */
if (utp) {
else if (connector == utp) {
GO_WINDOW(4);
outw(ENABLE_UTP, BASE + EP_W4_MEDIA_TYPE);
sleep(2); /* Give time for media to negotiate */
GO_WINDOW(1);
}
}
/* start tranciever and receiver */
/* start transceiver and receiver */
outw(RX_ENABLE, BASE + EP_COMMAND);
outw(TX_ENABLE, BASE + EP_COMMAND);
/* set early threshold for minimal packet length */
outw(SET_RX_EARLY_THRESH | ETH_MIN_PACKET, BASE + EP_COMMAND);
outw(SET_RX_EARLY_THRESH | ETH_ZLEN, BASE + EP_COMMAND);
outw(SET_TX_START_THRESH | 16, BASE + EP_COMMAND);
}
@ -171,17 +162,14 @@ const char *p) /* Packet */
int pad;
int status;
if(eth_vendor != VENDOR_3C509)
return;
#ifdef EDEBUG
printf("{l=%d,t=%x}",s+ETHER_HDR_SIZE,t);
printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
#endif
/* swap bytes of type */
t= htons(t);
len=s+ETHER_HDR_SIZE; /* actual length of packet */
len=s+ETH_HLEN; /* actual length of packet */
pad = padmap[len & 3];
/*
@ -189,30 +177,28 @@ const char *p) /* Packet */
* but we drop packets that are too large. Perhaps we should truncate
* them instead?
*/
if (len + pad > ETH_MAX_PACKET) {
if (len + pad > ETH_FRAME_LEN) {
return;
}
/* drop acknowledgements */
while(( status=inb(BASE + EP_W1_TX_STATUS) )& TXS_COMPLETE ) {
if(status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
while ((status=inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE ) {
if (status & (TXS_UNDERRUN|TXS_MAX_COLLISION|TXS_STATUS_OVERFLOW)) {
outw(TX_RESET, BASE + EP_COMMAND);
outw(TX_ENABLE, BASE + EP_COMMAND);
}
outb(0x0, BASE + EP_W1_TX_STATUS);
}
while (inw(BASE + EP_W1_FREE_TX) < (unsigned short)len + pad + 4) {
/* no room in FIFO */
}
while (inw(BASE + EP_W1_FREE_TX) < (unsigned short)len + pad + 4)
; /* no room in FIFO */
outw(len, BASE + EP_W1_TX_PIO_WR_1);
outw(0x0, BASE + EP_W1_TX_PIO_WR_1); /* Second dword meaningless */
/* write packet */
outsw(BASE + EP_W1_TX_PIO_WR_1, d, ETHER_ADDR_SIZE/2);
outsw(BASE + EP_W1_TX_PIO_WR_1, nic->node_addr, ETHER_ADDR_SIZE/2);
outsw(BASE + EP_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
outsw(BASE + EP_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
outw(t, BASE + EP_W1_TX_PIO_WR_1);
outsw(BASE + EP_W1_TX_PIO_WR_1, p, s / 2);
if (s & 1)
@ -221,8 +207,9 @@ const char *p) /* Packet */
while (pad--)
outb(0, BASE + EP_W1_TX_PIO_WR_1); /* Padding */
/* timeout after sending */
DELAY(1000);
/* wait for Tx complete */
while((inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
;
}
/**************************************************************************
@ -236,14 +223,11 @@ static int t509_poll(struct nic *nic)
short status, cst;
register short rx_fifo;
if(eth_vendor!=VENDOR_3C509)
return 0;
cst=inw(BASE + EP_STATUS);
#ifdef EDEBUG
if(cst & 0x1FFF)
printf("-%x-",cst);
printf("-%hX-",cst);
#endif
if( (cst & S_RX_COMPLETE)==0 ) {
@ -256,7 +240,7 @@ static int t509_poll(struct nic *nic)
status = inw(BASE + EP_W1_RX_STATUS);
#ifdef EDEBUG
printf("*%x*",status);
printf("*%hX*",status);
#endif
if (status & ERR_RX) {
@ -280,10 +264,9 @@ static int t509_poll(struct nic *nic)
while(1) {
status = inw(BASE + EP_W1_RX_STATUS);
#ifdef EDEBUG
printf("*%x*",status);
printf("*%hX*",status);
#endif
rx_fifo = status & RX_BYTES_MASK;
if(rx_fifo>0) {
insw(BASE + EP_W1_RX_PIO_RD_1, nic->packet+nic->packetlen, rx_fifo / 2);
if(rx_fifo & 1)
@ -293,32 +276,29 @@ static int t509_poll(struct nic *nic)
printf("+%d",rx_fifo);
#endif
}
if(( status & RX_INCOMPLETE )==0) {
#ifdef EDEBUG
printf("=%d",nic->packetlen);
#endif
break;
}
DELAY(1000);
udelay(1000); /* if incomplete wait 1 ms */
}
/* acknowledge reception of packet */
outw(RX_DISCARD_TOP_PACK, BASE + EP_COMMAND);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS);
while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS)
;
#ifdef EDEBUG
type = (nic->packet[12]<<8) | nic->packet[13];
if(nic->packet[0]+nic->packet[1]+nic->packet[2]+nic->packet[3]+nic->packet[4]+
nic->packet[5] == 0xFF*ETHER_ADDR_SIZE)
printf(",t=0x%x,b]",type);
nic->packet[5] == 0xFF*ETH_ALEN)
printf(",t=%hX,b]",type);
else
printf(",t=0x%x]",type);
printf(",t=%hX]",type);
#endif
return 1;
return (1);
}
/*************************************************************************
3Com 509 - specific routines
**************************************************************************/
@ -384,7 +364,8 @@ get_eeprom_data(int id_port, int offset)
{
int i, data = 0;
outb(0x80 + offset, id_port);
DELAY(10000);
/* Do we really need this wait? Won't be noticeable anyway */
udelay(10000);
for (i = 0; i < 16; i++)
data = (data << 1) | (inw(id_port) & 1);
return (data);
@ -415,11 +396,10 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
t509_disable(nic); /* in case board was active */
/* note that nic is not used */
for (failcount=0; failcount<4000; failcount++) {
int data, j, io_base, id_port = EP_ID_PORT;
for (failcount = 0; failcount < 4000; failcount++) {
int data, j, io_base, id_port;
unsigned short k;
int ep_current_tag = EP_LAST_TAG + 1;
int ep_current_tag;
short *p;
#ifdef INCLUDE_3C529
int curboard;
@ -427,7 +407,6 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
id_port = EP_ID_PORT;
ep_current_tag = EP_LAST_TAG + 1;
eth_vendor = VENDOR_NONE;
/*********************************************************
Search for 3Com 509 card
@ -476,8 +455,6 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
outb_p(0, MCA_ADAPTER_SETUP_REG);
if (mcafound) {
eth_vendor = VENDOR_3C509;
eth_nic_base = ((short)((mca_pos4&0xfc)|0x02)) << 8;
mca_irq = mca_pos5 & 0x0f;
ep_current_tag--;
@ -487,18 +464,18 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
#endif
/* Look for the EISA boards, leave them activated */
/* search for the first card, ignore all others */
for(j = 1; j < 16 && eth_vendor==VENDOR_NONE ; j++) {
for(j = 1; j < 16; j++) {
io_base = (j * EP_EISA_START) | EP_EISA_W0;
if (inw(io_base + EP_W0_MFG_ID) != MFG_ID)
continue;
/* we must found 0x1f if the board is EISA configurated */
/* we must have found 0x1f if the board is EISA configurated */
if ((inw(io_base + EP_W0_ADDRESS_CFG) & 0x1f) != 0x1f)
continue;
/* Reset and Enable the card */
outb(W0_P4_CMD_RESET_ADAPTER, io_base + EP_W0_CONFIG_CTRL);
DELAY(10000); /* we must wait at least 10 ms */
udelay(1000); /* Must wait 800 µs, be conservative */
outb(W0_P4_CMD_ENABLE_ADAPTER, io_base + EP_W0_CONFIG_CTRL);
/*
@ -506,15 +483,15 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
* x000 - x00F, where x is the slot number.
*/
eth_nic_base = j * EP_EISA_START;
eth_vendor = VENDOR_3C509;
break;
}
ep_current_tag--;
/* Look for the ISA boards. Init and leave them actived */
/* search for the first card, ignore all others */
outb(0xc0, id_port); /* Global reset */
DELAY(10000);
for (i = 0; i < EP_MAX_BOARDS && eth_vendor==VENDOR_NONE; i++) {
udelay(1000); /* wait 1 ms */
for (i = 0; i < EP_MAX_BOARDS; i++) {
outb(0, id_port);
outb(0, id_port);
send_ID_sequence(id_port);
@ -531,11 +508,11 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
(get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200;
outb(ep_current_tag, id_port); /* tags board */
outb(ACTIVATE_ADAPTER_TO_CONFIG, id_port);
eth_vendor = VENDOR_3C509;
ep_current_tag--;
break;
}
if(eth_vendor != VENDOR_3C509)
if (i >= EP_MAX_BOARDS)
goto no3c509;
/*
@ -550,7 +527,7 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
*/
if (mcafound) {
if (mcafound->id != k) {
printf("MCA: PROD_ID in EEPROM does not match MCA card ID! (%x != %x)\n", k, mcafound->id);
printf("MCA: PROD_ID in EEPROM does not match MCA card ID! (%hX != %hX)\n", k, mcafound->id);
goto no3c509;
}
} else { /* for ISA/EISA */
@ -564,15 +541,14 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
#ifdef INCLUDE_3C529
if (mcafound) {
printf("%s board found on MCA at 0x%x IRQ %d -",
printf("%s board found on MCA at %#hx IRQ %d -",
mcafound->name, eth_nic_base, mca_irq);
} else {
#endif
if(eth_nic_base >= EP_EISA_START) {
printf("3C5x9 board on EISA at 0x%x - ",eth_nic_base);
} else {
printf("3C5x9 board on ISA at 0x%x - ",eth_nic_base);
}
if(eth_nic_base >= EP_EISA_START)
printf("3C5x9 board on EISA at %#hx - ",eth_nic_base);
else
printf("3C5x9 board on ISA at %#hx - ",eth_nic_base);
#ifdef INCLUDE_3C529
}
#endif
@ -583,61 +559,48 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
switch(j) {
case 0:
if(i & IS_UTP) {
if (i & IS_UTP) {
printf("10baseT\n");
utp=1;
connector = utp;
}
else {
printf("10baseT not present\n");
eth_vendor=VENDOR_NONE;
goto no3c509;
}
break;
case 1:
if(i & IS_AUI)
if (i & IS_AUI)
printf("10base5\n");
else {
printf("10base5 not present\n");
eth_vendor=VENDOR_NONE;
goto no3c509;
}
break;
case 3:
if(i & IS_BNC) {
if (i & IS_BNC) {
printf("10base2\n");
bnc=1;
connector = bnc;
}
else {
printf("10base2 not present\n");
eth_vendor=VENDOR_NONE;
goto no3c509;
}
break;
default:
printf("unknown connector\n");
eth_vendor=VENDOR_NONE;
goto no3c509;
}
/*
* Read the station address from the eeprom
*/
p = (unsigned short *) nic->node_addr;
for (i = 0; i < 3; i++) {
for (i = 0; i < ETH_ALEN / 2; i++) {
GO_WINDOW(0);
p[i] = htons(get_e(i));
GO_WINDOW(2);
outw(ntohs(p[i]), BASE + EP_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]);
printf("Ethernet address: %!\n", nic->node_addr);
t509_reset(nic);
nic->reset = t509_reset;
nic->poll = t509_poll;
@ -645,7 +608,6 @@ struct nic *t509_probe(struct nic *nic, unsigned short *probe_addrs)
nic->disable = t509_disable;
return nic;
no3c509:
eth_vendor = VENDOR_NONE;
printf("(probe fail)");
}
return 0;
@ -656,4 +618,3 @@ no3c509:
* c-basic-offset: 8
* End:
*/

View file

@ -395,4 +395,3 @@
* c-basic-offset: 8
* End:
*/

View file

@ -28,8 +28,8 @@
#include "nic.h"
#include "pci.h"
#include "3c595.h"
#include "timer.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;
@ -57,34 +57,7 @@ static struct connector_entry {
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();
}
}
#define udelay(n) waiton_timer2(((n)*TICKS_PER_MS)/1000)
/**************************************************************************
ETH_RESET - Reset adapter
@ -103,7 +76,7 @@ static void t595_reset(struct nic *nic)
VX_BUSY_WAIT;
outw(TX_DISABLE, BASE + VX_COMMAND);
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
DELAY(8000);
udelay(8000);
outw(RX_RESET, BASE + VX_COMMAND);
VX_BUSY_WAIT;
outw(TX_RESET, BASE + VX_COMMAND);
@ -132,7 +105,7 @@ static void t595_reset(struct nic *nic)
GO_WINDOW(2);
/* Reload the ether_addr. */
for (i = 0; i < ETHER_ADDR_SIZE; i++)
for (i = 0; i < ETH_ALEN; i++)
outb(nic->node_addr[i], BASE + VX_W2_ADDR_0 + i);
outw(RX_RESET, BASE + VX_COMMAND);
@ -193,26 +166,26 @@ unsigned int t, /* Type */
unsigned int s, /* size */
const char *p) /* Packet */
{
register unsigned int len;
register int len;
int pad;
int status;
#ifdef EDEBUG
printf("{l=%d,t=%x}",s+ETHER_HDR_SIZE,t);
printf("{l=%d,t=%hX}",s+ETH_HLEN,t);
#endif
/* swap bytes of type */
t= htons(t);
len=s+ETHER_HDR_SIZE; /* actual length of packet */
len=s+ETH_HLEN; /* actual length of packet */
pad = padmap[len & 3];
/*
* The 3c509 automatically pads short packets to minimum ethernet length,
* The 3c595 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) {
if (len + pad > ETH_FRAME_LEN) {
return;
}
@ -234,8 +207,8 @@ const char *p) /* Packet */
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);
outsw(BASE + VX_W1_TX_PIO_WR_1, d, ETH_ALEN/2);
outsw(BASE + VX_W1_TX_PIO_WR_1, nic->node_addr, ETH_ALEN/2);
outw(t, BASE + VX_W1_TX_PIO_WR_1);
outsw(BASE + VX_W1_TX_PIO_WR_1, p, s / 2);
if (s & 1)
@ -244,8 +217,9 @@ const char *p) /* Packet */
while (pad--)
outb(0, BASE + VX_W1_TX_PIO_WR_1); /* Padding */
/* timeout after sending */
DELAY(1000);
/* wait for Tx complete */
while((inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) != 0)
;
}
/**************************************************************************
@ -255,7 +229,7 @@ static int t595_poll(struct nic *nic)
{
/* common variables */
unsigned short type = 0; /* used by EDEBUG */
/* variables for 3C509 */
/* variables for 3C595 */
short status, cst;
register short rx_fifo;
@ -263,7 +237,7 @@ static int t595_poll(struct nic *nic)
#ifdef EDEBUG
if(cst & 0x1FFF)
printf("-%x-",cst);
printf("-%hX-",cst);
#endif
if( (cst & S_RX_COMPLETE)==0 ) {
@ -276,7 +250,7 @@ static int t595_poll(struct nic *nic)
status = inw(BASE + VX_W1_RX_STATUS);
#ifdef EDEBUG
printf("*%x*",status);
printf("*%hX*",status);
#endif
if (status & ERR_RX) {
@ -300,7 +274,7 @@ static int t595_poll(struct nic *nic)
while(1) {
status = inw(BASE + VX_W1_RX_STATUS);
#ifdef EDEBUG
printf("*%x*",status);
printf("*%hX*",status);
#endif
rx_fifo = status & RX_BYTES_MASK;
@ -313,15 +287,13 @@ static int t595_poll(struct nic *nic)
printf("+%d",rx_fifo);
#endif
}
if(( status & RX_INCOMPLETE )==0) {
#ifdef EDEBUG
printf("=%d",nic->packetlen);
#endif
break;
}
DELAY(1000);
udelay(1000);
}
/* acknowledge reception of packet */
@ -330,17 +302,17 @@ static int t595_poll(struct nic *nic)
#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);
nic->packet[5] == 0xFF*ETH_ALEN)
printf(",t=%hX,b]",type);
else
printf(",t=0x%x]",type);
printf(",t=%hX]",type);
#endif
return 1;
}
/*************************************************************************
3Com 509 - specific routines
3Com 595 - specific routines
**************************************************************************/
static int
@ -349,9 +321,9 @@ eeprom_rdy()
int i;
for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++)
DELAY(1000);
udelay(1000);
if (i >= MAX_EEPROMBUSY) {
/* printf("3c509: eeprom failed to come ready.\n"); */
/* printf("3c595: eeprom failed to come ready.\n"); */
printf("3c595: eeprom is busy.\n"); /* memory in EPROM is tight */
return (0);
}
@ -441,7 +413,7 @@ vxsetlink(void)
/* First, disable all. */
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
DELAY(8000);
udelay(8000);
GO_WINDOW(4);
outw(0, BASE + VX_W4_MEDIA_TYPE);
@ -453,7 +425,7 @@ vxsetlink(void)
break;
case CONNECTOR_BNC:
outw(START_TRANSCEIVER,BASE + VX_COMMAND);
DELAY(8000);
udelay(8000);
break;
case CONNECTOR_TX:
case CONNECTOR_FX:
@ -469,7 +441,7 @@ vxsetlink(void)
static void t595_disable(struct nic *nic)
{
outw(STOP_TRANSCEIVER, BASE + VX_COMMAND);
DELAY(8000);
udelay(8000);
GO_WINDOW(4);
outw(0, BASE + VX_W4_MEDIA_TYPE);
GO_WINDOW(1);
@ -497,7 +469,7 @@ struct nic *t595_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_d
/*
printf("\nEEPROM:");
for (i = 0; i < (EEPROMSIZE/2); i++) {
printf("%x:", get_e(i));
printf("%hX:", get_e(i));
}
printf("\n");
*/
@ -512,11 +484,7 @@ struct nic *t595_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_d
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]);
printf("Ethernet address: %!\n", nic->node_addr);
t595_reset(nic);
nic->reset = t595_reset;

View file

@ -38,8 +38,8 @@
#include "nic.h"
#include "pci.h"
#include "cards.h"
#include "timer.h"
#define TIME_OUT 60000
#define XCVR_MAGIC (0x5A00)
/** any single transmission fails after 16 collisions or other errors
** this is the number of times to retry the transmission -- this should
@ -243,7 +243,7 @@ static struct
unsigned char isBrev;
unsigned char CurrentWindow;
unsigned int IOAddr;
unsigned char HWAddr[6];
unsigned char HWAddr[ETH_ALEN];
TXD TransmitDPD;
RXD ReceiveUPD;
}
@ -479,13 +479,13 @@ a3c90x_transmit(struct nic *nic, const char *d, unsigned int t,
struct eth_hdr
{
unsigned char dst_addr[6];
unsigned char src_addr[6];
unsigned char dst_addr[ETH_ALEN];
unsigned char src_addr[ETH_ALEN];
unsigned short type;
} hdr;
unsigned char status;
unsigned timeout, i, retries;
unsigned i, retries;
for (retries=0; retries < XMIT_RETRIES ; retries++)
{
@ -504,10 +504,10 @@ a3c90x_transmit(struct nic *nic, const char *d, unsigned int t,
hdr.type = htons(t);
/** Copy the destination address **/
memcpy(hdr.dst_addr, d, 6);
memcpy(hdr.dst_addr, d, ETH_ALEN);
/** Copy our MAC address **/
memcpy(hdr.src_addr, INF_3C90X.HWAddr, 6);
memcpy(hdr.src_addr, INF_3C90X.HWAddr, ETH_ALEN);
/** Setup the DPD (download descriptor) **/
INF_3C90X.TransmitDPD.DnNextPtr = 0;
@ -528,12 +528,12 @@ a3c90x_transmit(struct nic *nic, const char *d, unsigned int t,
;
/** Wait for NIC Transmit to Complete **/
timeout=TIME_OUT;
load_timer2(10*TICKS_PER_MS); /* Give it 10 ms */
while (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004) &&
--timeout)
for(i=0;i<TIME_OUT;i++);
timer2_running())
;
if (timeout==0)
if (!(inw(INF_3C90X.IOAddr + regCommandIntStatus_w)&0x0004))
{
printf("3C90X: Tx Timeout\n");
continue;
@ -548,16 +548,16 @@ a3c90x_transmit(struct nic *nic, const char *d, unsigned int t,
if ((status & 0xbf) == 0x80)
return;
printf("3C90X: Status (%x)\n", status);
printf("3C90X: Status (%hhX)\n", status);
/** check error codes **/
if (status & 0x02)
{
printf("3C90X: Tx Reclaim Error (%x)\n", status);
printf("3C90X: Tx Reclaim Error (%hhX)\n", status);
a3c90x_reset(NULL);
}
else if (status & 0x04)
{
printf("3C90X: Tx Status Overflow (%x)\n", status);
printf("3C90X: Tx Status Overflow (%hhX)\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 **/
@ -565,23 +565,23 @@ a3c90x_transmit(struct nic *nic, const char *d, unsigned int t,
}
else if (status & 0x08)
{
printf("3C90X: Tx Max Collisions (%x)\n", status);
printf("3C90X: Tx Max Collisions (%hhX)\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: Tx Underrun (%x)\n", status);
printf("3C90X: Tx Underrun (%hhX)\n", status);
a3c90x_reset(NULL);
}
else if (status & 0x20)
{
printf("3C90X: Tx Jabber (%x)\n", status);
printf("3C90X: Tx Jabber (%hhX)\n", status);
a3c90x_reset(NULL);
}
else if ((status & 0x80) != 0x80)
{
printf("3C90X: Internal Error - Incomplete Transmission (%x)\n",
printf("3C90X: Internal Error - Incomplete Transmission (%hhX)\n",
status);
a3c90x_reset(NULL);
}
@ -634,17 +634,17 @@ a3c90x_poll(struct nic *nic)
{
errcode = INF_3C90X.ReceiveUPD.UpPktStatus;
if (errcode & (1<<16))
printf("3C90X: Rx Overrun (%x)\n",errcode>>16);
printf("3C90X: Rx Overrun (%hX)\n",errcode>>16);
else if (errcode & (1<<17))
printf("3C90X: Runt Frame (%x)\n",errcode>>16);
printf("3C90X: Runt Frame (%hX)\n",errcode>>16);
else if (errcode & (1<<18))
printf("3C90X: Alignment Error (%x)\n",errcode>>16);
printf("3C90X: Alignment Error (%hX)\n",errcode>>16);
else if (errcode & (1<<19))
printf("3C90X: CRC Error (%x)\n",errcode>>16);
printf("3C90X: CRC Error (%hX)\n",errcode>>16);
else if (errcode & (1<<20))
printf("3C90X: Oversized Frame (%x)\n",errcode>>16);
printf("3C90X: Oversized Frame (%hX)\n",errcode>>16);
else
printf("3C90X: Packet error (%x)\n",errcode>>16);
printf("3C90X: Packet error (%hX)\n",errcode>>16);
return 0;
}
@ -659,10 +659,15 @@ a3c90x_poll(struct nic *nic)
/*** 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?
*** Must turn off receiver at least so stray packets will not corrupt memory
*** [Ken]
***/
static void
a3c90x_disable(struct nic *nic)
{
/* Disable the receiver and transmitter. */
outw(cmdRxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w);
outw(cmdTxDisable, INF_3C90X.IOAddr + regCommandIntStatus_w);
}
@ -683,6 +688,8 @@ a3c90x_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_device *pci
if (probeaddrs == 0 || probeaddrs[0] == 0)
return 0;
adjust_pci_device(pci);
INF_3C90X.IOAddr = probeaddrs[0] & ~3;
INF_3C90X.CurrentWindow = 255;
switch (a3c90x_internal_ReadEeprom(INF_3C90X.IOAddr, 0x03))
@ -759,9 +766,7 @@ a3c90x_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_device *pci
INF_3C90X.HWAddr[3] = eeprom[1]&0xFF;
INF_3C90X.HWAddr[4] = eeprom[2]>>8;
INF_3C90X.HWAddr[5] = eeprom[2]&0xFF;
printf("MAC Address = %b:%b:%b:%b:%b:%b\n",
INF_3C90X.HWAddr[0],INF_3C90X.HWAddr[1],INF_3C90X.HWAddr[2],
INF_3C90X.HWAddr[3],INF_3C90X.HWAddr[4],INF_3C90X.HWAddr[5]);
printf("MAC Address = %!\n", INF_3C90X.HWAddr);
/** Program the MAC address into the station address registers **/
a3c90x_internal_SetWindow(INF_3C90X.IOAddr, winAddressing2);
@ -773,7 +778,8 @@ a3c90x_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_device *pci
outw(0, INF_3C90X.IOAddr + regStationMask_2_3w+4);
/** Fill in our entry in the etherboot arp table **/
for(i=0;i<6;i++) nic->node_addr[i] = (eeprom[i/2] >> (8*((i&1)^1))) & 0xff;
for(i=0;i<ETH_ALEN;i++)
nic->node_addr[i] = (eeprom[i/2] >> (8*((i&1)^1))) & 0xff;
/** Read the media options register, print a message and set default
** xcvr.

View file

@ -77,6 +77,10 @@ II FLASH PROMS
have heard problem reports of its use under FreeBSD. Anyone willing to
make it work under FreeBSD is more than welcome to do so!
You also have the option of using EPROM chips - the 3C905B-TX-NM has been
successfully tested with 27C256 (32kB) and 27C512 (64kB) chips with a
specified access time of 100ns and faster.
III GENERAL USE
@ -87,10 +91,10 @@ III GENERAL USE
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.
3. Run the floppy image on the PC to be network booted, to get
it configured, and 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.
it into the flash or EPROM memory chip.
5. Put the PROM in the ethernet card, boot and enable 'boot from
network first' in the system BIOS, save and reboot.
@ -100,6 +104,8 @@ III GENERAL USE
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.
Please note that you have to boot off a floppy (not PROM!) once for
this fix to take effect.
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
@ -160,7 +166,9 @@ III GENERAL USE
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.
booting from the Flash ROM, define -DCFG_3C90X_BOOTROM_FIX when building,
create a floppy image and boot it once.
Thereafter, the card should accept the larger prom image.
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
@ -276,3 +284,24 @@ IV FOR DEVELOPERS....
number. Another driver used 't' (for 'three'?); I chose 'a' for
no reason at all.
Addendum by Jorge L. deLyra <delyra@latt.if.usp.br>, 22Nov2000 re
working around the 3C905 hardware bug mentioned above:
Use this floppy to fix any 3COM model 3C905B PCI 10/100 Ethernet cards
that fail to load and run the boot program the first time around. If
they have a "Lucent" rather than a "Broadcom" chipset these cards have
a configuration bug that causes a hang when trying to load the boot
program from the PROM, if you try to use them right out of the box.
The boot program in this floppy is the file named 3c905b-tpo100.rom
from Etherboot version 4.6.10, compiled with the bugfix parameter
CFG_3C90X_BOOTROM_FIX
You have to take the chip off the card and boot the system once using
this floppy. Once loaded from the floppy, the boot program will access
the card and change some setting in it, correcting the problem. After
that you may use either this boot program or the normal one, compiled
without this bugfix parameter, to boot the machine from the PROM chip.
[Any recent Etherboot version should do, not just 4.6.10 - Ed.]

View file

@ -12,53 +12,52 @@ noinst_LIBRARIES = $(LIBDRIVERS)
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
main.c misc.c nic.h osdep.h pci.c pci.h timer.c timer.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
cs89x0.c cs89x0.h davicom.c depca.c eepro.c eepro100.c \
epic100.c epic100.h fa311.c i82586.c lance.c natsemi.c \
ni5010.c ns8390.c ns8390.h otulip.c otulip.h rtl8139.c \
sis900.c sis900.h sk_g16.c sk_g16.h smc9000.c smc9000.h \
tiara.c tlan.c tulip.c via-rhine.c w89c840.c
libdrivers_a_CFLAGS = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-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 cs89x0.txt tulip.txt
EXTRA_DIST = README.netboot 3c90x.txt cs89x0.txt sis900.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
3c595_drivers = 3c590.o 3c595.o
3c595_drivers = 3c595.o
3c90x_drivers = 3c90x.o
cs89x0_drivers = cs89x0.o
davicom_drivers = davicom.o
depca_drivers = depca.o
eepro_drivers = eepro.o
eepro100_drivers = eepro100.o
epic100_drivers = epic100.o
#fa311_drivers = fa311.o
i82586_drivers = 3c507.o exos205.o ni5210.o
lance_drivers = lance.o ne2100.o ni6510.o
natsemi_drivers = natsemi.o
ni5010_drivers = ni5010.o
ns8390_drivers = 3c503.o ne.o ns8390.o wd.o
otulip_drivers = otulip.o
rtl8139_drivers = rtl8139.o
sis900_drivers = sis900.o
sk_g16_drivers = sk_g16.o
smc9000_drivers = smc9000.o
tiara_drivers = tiara.o
#tlan_drivers = tlan.o
tulip_drivers = tulip.o
via_rhine_drivers = via_rhine.o
w89c840_drivers = w89c840.o
# Is it really necessary to specify dependecies explicitly?
$(ns8390_drivers): ns8390.c ns8390.h
$(ns8390_drivers): %.o: ns8390.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(i82586_drivers): i82586.c
$(i82586_drivers): %.o: i82586.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(3c509_drivers): 3c509.c 3c509.h
$(3c509_drivers): %.o: 3c509.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
@ -79,11 +78,21 @@ $(cs89x0_drivers): %.o: cs89x0.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(davicom_drivers): davicom.c
$(davicom_drivers): %.o: davicom.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 $<
$(eepro_drivers): eepro.c
$(eepro_drivers): %.o: eepro.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 \
@ -94,13 +103,38 @@ $(epic100_drivers): %.o: epic100.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
#$(fa311_drivers): fa311.c
#$(fa311_drivers): %.o: fa311.c
# $(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
# $(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(i82586_drivers): i82586.c
$(i82586_drivers): %.o: i82586.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(lance_drivers): lance.c
$(lance_drivers): %.o: lance.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(tulip_drivers): tulip.c
$(tulip_drivers): %.o: tulip.c
$(natsemi_drivers): natsemi.c
$(natsemi_drivers): %.o: natsemi.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(ni5010_drivers): ni5010.c
$(ni5010_drivers): %.o: ni5010.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(ns8390_drivers): ns8390.c ns8390.h
$(ns8390_drivers): %.o: ns8390.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -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 $<
@ -109,6 +143,11 @@ $(rtl8139_drivers): %.o: rtl8139.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(sis900_drivers): sis900.c
$(sis900_drivers): %.o: sis900.c sis900.h
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(sk_g16_drivers): sk_g16.c sk_g16.h
$(sk_g16_drivers): %.o: sk_g16.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
@ -124,8 +163,13 @@ $(tiara_drivers): %.o: tiara.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(otulip_drivers): otulip.c otulip.h
$(otulip_drivers): %.o: otulip.c
#$(tlan_drivers): tlan.c
#$(tlan_drivers): %.o: tlan.c
# $(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
# $(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(tulip_drivers): tulip.c
$(tulip_drivers): %.o: tulip.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
@ -134,31 +178,42 @@ $(via_rhine_drivers): %.o: via-rhine.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(w89c840_drivers): w89c840.c
$(w89c840_drivers): %.o: w89c840.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
# Per-object flags.
3c509_o_CFLAGS = -DINCLUDE_3C509=1
3c529_o_CFLAGS = -DINCLUDE_3C529=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
davicom_o_CFLAGS = -DINCLUDE_DAVICOM=1
depca_o_CFLAGS = -DINCLUDE_DEPCA=1
eepro_o_CFLAGS = -DINCLUDE_EEPRO=1
eepro100_o_CFLAGS = -DINCLUDE_EEPRO100=1
epic100_o_CFLAGS = -DINCLUDE_EPIC100=1
#fa311_o_CFLAGS = -DINCLUDE_FA311=1
3c507_o_CFLAGS = -DINCLUDE_3C507=1
exos205_o_CFLAGS = -DINCLUDE_EXOS205=1
ni5210_o_CFLAGS = -DINCLUDE_NI5210=1
lance_o_CFLAGS = -DINCLUDE_LANCE=1
ne2100_o_CFLAGS = -DINCLUDE_NE2100=1
ni6510_o_CFLAGS = -DINCLUDE_NI6510=1
natsemi_o_CFLAGS = -DINCLUDE_NATSEMI=1
ni5010_o_CFLAGS = -DINCLUDE_NI5010=1
3c503_o_CFLAGS = -DINCLUDE_3C503=1
ne_o_CFLAGS = -DINCLUDE_NE=1
ns8390_o_CFLAGS = -DINCLUDE_NS8390=1
wd_o_CFLAGS = -DINCLUDE_WD=1
otulip_o_CFLAGS = -DINCLUDE_OTULIP=1
rtl8139_o_CFLAGS = -DINCLUDE_RTL8139=1
sis900_o_CFLAGS = -DINCLUDE_SIS900=1
sk_g16_o_CFLAGS = -DINCLUDE_SK_G16=1
smc9000_o_CFLAGS = -DINCLUDE_SMC9000=1
tiara_o_CFLAGS = -DINCLUDE_TIARA=1
#tlan_o_CFLAGS = -DINCLUDE_TLAN=1
tulip_o_CFLAGS = -DINCLUDE_TULIP=1
via_rhine_o_CFLAGS = -DINCLUDE_VIA_RHINE=1
w89c840_o_CFLAGS = -DINCLUDE_W89C840=1

View file

@ -98,13 +98,14 @@ noinst_LIBRARIES = $(LIBDRIVERS)
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
main.c misc.c nic.h osdep.h pci.c pci.h timer.c timer.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
cs89x0.c cs89x0.h davicom.c depca.c eepro.c eepro100.c \
epic100.c epic100.h fa311.c i82586.c lance.c natsemi.c \
ni5010.c ns8390.c ns8390.h otulip.c otulip.h rtl8139.c \
sis900.c sis900.h sk_g16.c sk_g16.h smc9000.c smc9000.h \
tiara.c tlan.c tulip.c via-rhine.c w89c840.c
libdrivers_a_CFLAGS = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
-DFSYS_TFTP=1 $(NET_CFLAGS) $(NET_EXTRAFLAGS)
@ -113,57 +114,72 @@ libdrivers_a_CFLAGS = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
libdrivers_a_LIBADD = @NETBOOT_DRIVERS@
libdrivers_a_DEPENDENCIES = $(libdrivers_a_LIBADD)
EXTRA_DIST = README.netboot 3c90x.txt cs89x0.txt tulip.txt
EXTRA_DIST = README.netboot 3c90x.txt cs89x0.txt sis900.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
3c595_drivers = 3c590.o 3c595.o
3c595_drivers = 3c595.o
3c90x_drivers = 3c90x.o
cs89x0_drivers = cs89x0.o
davicom_drivers = davicom.o
depca_drivers = depca.o
eepro_drivers = eepro.o
eepro100_drivers = eepro100.o
epic100_drivers = epic100.o
#fa311_drivers = fa311.o
i82586_drivers = 3c507.o exos205.o ni5210.o
lance_drivers = lance.o ne2100.o ni6510.o
natsemi_drivers = natsemi.o
ni5010_drivers = ni5010.o
ns8390_drivers = 3c503.o ne.o ns8390.o wd.o
otulip_drivers = otulip.o
rtl8139_drivers = rtl8139.o
sis900_drivers = sis900.o
sk_g16_drivers = sk_g16.o
smc9000_drivers = smc9000.o
tiara_drivers = tiara.o
#tlan_drivers = tlan.o
tulip_drivers = tulip.o
via_rhine_drivers = via_rhine.o
w89c840_drivers = w89c840.o
# Per-object flags.
3c509_o_CFLAGS = -DINCLUDE_3C509=1
3c529_o_CFLAGS = -DINCLUDE_3C529=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
davicom_o_CFLAGS = -DINCLUDE_DAVICOM=1
depca_o_CFLAGS = -DINCLUDE_DEPCA=1
eepro_o_CFLAGS = -DINCLUDE_EEPRO=1
eepro100_o_CFLAGS = -DINCLUDE_EEPRO100=1
epic100_o_CFLAGS = -DINCLUDE_EPIC100=1
#fa311_o_CFLAGS = -DINCLUDE_FA311=1
3c507_o_CFLAGS = -DINCLUDE_3C507=1
exos205_o_CFLAGS = -DINCLUDE_EXOS205=1
ni5210_o_CFLAGS = -DINCLUDE_NI5210=1
lance_o_CFLAGS = -DINCLUDE_LANCE=1
ne2100_o_CFLAGS = -DINCLUDE_NE2100=1
ni6510_o_CFLAGS = -DINCLUDE_NI6510=1
natsemi_o_CFLAGS = -DINCLUDE_NATSEMI=1
ni5010_o_CFLAGS = -DINCLUDE_NI5010=1
3c503_o_CFLAGS = -DINCLUDE_3C503=1
ne_o_CFLAGS = -DINCLUDE_NE=1
ns8390_o_CFLAGS = -DINCLUDE_NS8390=1
wd_o_CFLAGS = -DINCLUDE_WD=1
otulip_o_CFLAGS = -DINCLUDE_OTULIP=1
rtl8139_o_CFLAGS = -DINCLUDE_RTL8139=1
sis900_o_CFLAGS = -DINCLUDE_SIS900=1
sk_g16_o_CFLAGS = -DINCLUDE_SK_G16=1
smc9000_o_CFLAGS = -DINCLUDE_SMC9000=1
tiara_o_CFLAGS = -DINCLUDE_TIARA=1
#tlan_o_CFLAGS = -DINCLUDE_TLAN=1
tulip_o_CFLAGS = -DINCLUDE_TULIP=1
via_rhine_o_CFLAGS = -DINCLUDE_VIA_RHINE=1
w89c840_o_CFLAGS = -DINCLUDE_W89C840=1
subdir = netboot
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
@ -173,7 +189,8 @@ LIBRARIES = $(noinst_LIBRARIES)
libdrivers_a_AR = $(AR) cru
am_libdrivers_a_OBJECTS = libdrivers_a-config.$(OBJEXT) \
libdrivers_a-fsys_tftp.$(OBJEXT) libdrivers_a-main.$(OBJEXT) \
libdrivers_a-misc.$(OBJEXT) libdrivers_a-pci.$(OBJEXT)
libdrivers_a-misc.$(OBJEXT) libdrivers_a-pci.$(OBJEXT) \
libdrivers_a-timer.$(OBJEXT)
libdrivers_a_OBJECTS = $(am_libdrivers_a_OBJECTS)
DEFS = @DEFS@
@ -187,23 +204,32 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-3c90x.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-config.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-cs89x0.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-davicom.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-depca.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-eepro.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-eepro100.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-epic100.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-fa311.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-fsys_tftp.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-i82586.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-lance.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-main.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-misc.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-natsemi.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-ni5010.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-ns8390.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-otulip.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-pci.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-rtl8139.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-sis900.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-sk_g16.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-smc9000.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-tiara.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-timer.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-tlan.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-tulip.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-via-rhine.Po
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-via-rhine.Po \
@AMDEP_TRUE@ $(DEPDIR)/libdrivers_a-w89c840.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
@ -234,23 +260,32 @@ libdrivers_a-fsys_tftp.$(OBJEXT): fsys_tftp.c
libdrivers_a-main.$(OBJEXT): main.c
libdrivers_a-misc.$(OBJEXT): misc.c
libdrivers_a-pci.$(OBJEXT): pci.c
libdrivers_a-timer.$(OBJEXT): timer.c
libdrivers_a-3c509.$(OBJEXT): 3c509.c
libdrivers_a-3c595.$(OBJEXT): 3c595.c
libdrivers_a-3c90x.$(OBJEXT): 3c90x.c
libdrivers_a-cs89x0.$(OBJEXT): cs89x0.c
libdrivers_a-davicom.$(OBJEXT): davicom.c
libdrivers_a-depca.$(OBJEXT): depca.c
libdrivers_a-eepro.$(OBJEXT): eepro.c
libdrivers_a-eepro100.$(OBJEXT): eepro100.c
libdrivers_a-epic100.$(OBJEXT): epic100.c
libdrivers_a-fa311.$(OBJEXT): fa311.c
libdrivers_a-i82586.$(OBJEXT): i82586.c
libdrivers_a-lance.$(OBJEXT): lance.c
libdrivers_a-natsemi.$(OBJEXT): natsemi.c
libdrivers_a-ni5010.$(OBJEXT): ni5010.c
libdrivers_a-ns8390.$(OBJEXT): ns8390.c
libdrivers_a-otulip.$(OBJEXT): otulip.c
libdrivers_a-rtl8139.$(OBJEXT): rtl8139.c
libdrivers_a-sis900.$(OBJEXT): sis900.c
libdrivers_a-sk_g16.$(OBJEXT): sk_g16.c
libdrivers_a-smc9000.$(OBJEXT): smc9000.c
libdrivers_a-tiara.$(OBJEXT): tiara.c
libdrivers_a-tlan.$(OBJEXT): tlan.c
libdrivers_a-tulip.$(OBJEXT): tulip.c
libdrivers_a-via-rhine.$(OBJEXT): via-rhine.c
libdrivers_a-w89c840.$(OBJEXT): w89c840.c
libdrivers.a: $(libdrivers_a_OBJECTS) $(libdrivers_a_DEPENDENCIES)
-rm -f libdrivers.a
$(libdrivers_a_AR) libdrivers.a $(libdrivers_a_OBJECTS) $(libdrivers_a_LIBADD)
@ -267,23 +302,32 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-3c90x.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-config.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-cs89x0.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-davicom.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-depca.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-eepro.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-eepro100.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-epic100.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-fa311.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-fsys_tftp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-i82586.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-lance.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-main.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-misc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-natsemi.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-ni5010.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-ns8390.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-otulip.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-pci.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-rtl8139.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-sis900.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-sk_g16.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-smc9000.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-tiara.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-timer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-tlan.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-tulip.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-via-rhine.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/libdrivers_a-w89c840.Po@am__quote@
distclean-depend:
-rm -rf $(DEPDIR)
@ -360,6 +404,18 @@ libdrivers_a-pci.obj: pci.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-pci.obj `cygpath -w pci.c`
libdrivers_a-timer.o: timer.c
@AMDEP_TRUE@ source='timer.c' object='libdrivers_a-timer.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-timer.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-timer.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-timer.o `test -f timer.c || echo '$(srcdir)/'`timer.c
libdrivers_a-timer.obj: timer.c
@AMDEP_TRUE@ source='timer.c' object='libdrivers_a-timer.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-timer.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-timer.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-timer.obj `cygpath -w timer.c`
libdrivers_a-3c509.o: 3c509.c
@AMDEP_TRUE@ source='3c509.c' object='libdrivers_a-3c509.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-3c509.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-3c509.TPo' @AMDEPBACKSLASH@
@ -408,6 +464,18 @@ libdrivers_a-cs89x0.obj: cs89x0.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-cs89x0.obj `cygpath -w cs89x0.c`
libdrivers_a-davicom.o: davicom.c
@AMDEP_TRUE@ source='davicom.c' object='libdrivers_a-davicom.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-davicom.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-davicom.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-davicom.o `test -f davicom.c || echo '$(srcdir)/'`davicom.c
libdrivers_a-davicom.obj: davicom.c
@AMDEP_TRUE@ source='davicom.c' object='libdrivers_a-davicom.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-davicom.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-davicom.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-davicom.obj `cygpath -w davicom.c`
libdrivers_a-depca.o: depca.c
@AMDEP_TRUE@ source='depca.c' object='libdrivers_a-depca.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-depca.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-depca.TPo' @AMDEPBACKSLASH@
@ -420,6 +488,18 @@ libdrivers_a-depca.obj: depca.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-depca.obj `cygpath -w depca.c`
libdrivers_a-eepro.o: eepro.c
@AMDEP_TRUE@ source='eepro.c' object='libdrivers_a-eepro.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-eepro.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-eepro.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-eepro.o `test -f eepro.c || echo '$(srcdir)/'`eepro.c
libdrivers_a-eepro.obj: eepro.c
@AMDEP_TRUE@ source='eepro.c' object='libdrivers_a-eepro.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-eepro.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-eepro.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-eepro.obj `cygpath -w eepro.c`
libdrivers_a-eepro100.o: eepro100.c
@AMDEP_TRUE@ source='eepro100.c' object='libdrivers_a-eepro100.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-eepro100.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-eepro100.TPo' @AMDEPBACKSLASH@
@ -444,6 +524,18 @@ libdrivers_a-epic100.obj: epic100.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-epic100.obj `cygpath -w epic100.c`
libdrivers_a-fa311.o: fa311.c
@AMDEP_TRUE@ source='fa311.c' object='libdrivers_a-fa311.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-fa311.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-fa311.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-fa311.o `test -f fa311.c || echo '$(srcdir)/'`fa311.c
libdrivers_a-fa311.obj: fa311.c
@AMDEP_TRUE@ source='fa311.c' object='libdrivers_a-fa311.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-fa311.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-fa311.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-fa311.obj `cygpath -w fa311.c`
libdrivers_a-i82586.o: i82586.c
@AMDEP_TRUE@ source='i82586.c' object='libdrivers_a-i82586.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-i82586.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-i82586.TPo' @AMDEPBACKSLASH@
@ -468,6 +560,30 @@ libdrivers_a-lance.obj: lance.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-lance.obj `cygpath -w lance.c`
libdrivers_a-natsemi.o: natsemi.c
@AMDEP_TRUE@ source='natsemi.c' object='libdrivers_a-natsemi.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-natsemi.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-natsemi.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-natsemi.o `test -f natsemi.c || echo '$(srcdir)/'`natsemi.c
libdrivers_a-natsemi.obj: natsemi.c
@AMDEP_TRUE@ source='natsemi.c' object='libdrivers_a-natsemi.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-natsemi.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-natsemi.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-natsemi.obj `cygpath -w natsemi.c`
libdrivers_a-ni5010.o: ni5010.c
@AMDEP_TRUE@ source='ni5010.c' object='libdrivers_a-ni5010.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-ni5010.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-ni5010.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-ni5010.o `test -f ni5010.c || echo '$(srcdir)/'`ni5010.c
libdrivers_a-ni5010.obj: ni5010.c
@AMDEP_TRUE@ source='ni5010.c' object='libdrivers_a-ni5010.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-ni5010.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-ni5010.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-ni5010.obj `cygpath -w ni5010.c`
libdrivers_a-ns8390.o: ns8390.c
@AMDEP_TRUE@ source='ns8390.c' object='libdrivers_a-ns8390.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-ns8390.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-ns8390.TPo' @AMDEPBACKSLASH@
@ -504,6 +620,18 @@ libdrivers_a-rtl8139.obj: rtl8139.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-rtl8139.obj `cygpath -w rtl8139.c`
libdrivers_a-sis900.o: sis900.c
@AMDEP_TRUE@ source='sis900.c' object='libdrivers_a-sis900.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-sis900.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-sis900.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-sis900.o `test -f sis900.c || echo '$(srcdir)/'`sis900.c
libdrivers_a-sis900.obj: sis900.c
@AMDEP_TRUE@ source='sis900.c' object='libdrivers_a-sis900.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-sis900.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-sis900.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-sis900.obj `cygpath -w sis900.c`
libdrivers_a-sk_g16.o: sk_g16.c
@AMDEP_TRUE@ source='sk_g16.c' object='libdrivers_a-sk_g16.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-sk_g16.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-sk_g16.TPo' @AMDEPBACKSLASH@
@ -540,6 +668,18 @@ libdrivers_a-tiara.obj: tiara.c
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-tiara.obj `cygpath -w tiara.c`
libdrivers_a-tlan.o: tlan.c
@AMDEP_TRUE@ source='tlan.c' object='libdrivers_a-tlan.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-tlan.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-tlan.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-tlan.o `test -f tlan.c || echo '$(srcdir)/'`tlan.c
libdrivers_a-tlan.obj: tlan.c
@AMDEP_TRUE@ source='tlan.c' object='libdrivers_a-tlan.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-tlan.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-tlan.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-tlan.obj `cygpath -w tlan.c`
libdrivers_a-tulip.o: tulip.c
@AMDEP_TRUE@ source='tulip.c' object='libdrivers_a-tulip.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-tulip.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-tulip.TPo' @AMDEPBACKSLASH@
@ -563,6 +703,18 @@ libdrivers_a-via-rhine.obj: via-rhine.c
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-via-rhine.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-via-rhine.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-via-rhine.obj `cygpath -w via-rhine.c`
libdrivers_a-w89c840.o: w89c840.c
@AMDEP_TRUE@ source='w89c840.c' object='libdrivers_a-w89c840.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-w89c840.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-w89c840.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-w89c840.o `test -f w89c840.c || echo '$(srcdir)/'`w89c840.c
libdrivers_a-w89c840.obj: w89c840.c
@AMDEP_TRUE@ source='w89c840.c' object='libdrivers_a-w89c840.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/libdrivers_a-w89c840.Po' tmpdepfile='$(DEPDIR)/libdrivers_a-w89c840.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libdrivers_a_CFLAGS) $(CFLAGS) -c -o libdrivers_a-w89c840.obj `cygpath -w w89c840.c`
CCDEPMODE = @CCDEPMODE@
uninstall-info-am:
@ -698,16 +850,6 @@ uninstall-am: uninstall-info-am
# Is it really necessary to specify dependecies explicitly?
$(ns8390_drivers): ns8390.c ns8390.h
$(ns8390_drivers): %.o: ns8390.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(i82586_drivers): i82586.c
$(i82586_drivers): %.o: i82586.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(3c509_drivers): 3c509.c 3c509.h
$(3c509_drivers): %.o: 3c509.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
@ -728,11 +870,21 @@ $(cs89x0_drivers): %.o: cs89x0.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(davicom_drivers): davicom.c
$(davicom_drivers): %.o: davicom.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 $<
$(eepro_drivers): eepro.c
$(eepro_drivers): %.o: eepro.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 \
@ -743,13 +895,38 @@ $(epic100_drivers): %.o: epic100.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
#$(fa311_drivers): fa311.c
#$(fa311_drivers): %.o: fa311.c
# $(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
# $(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(i82586_drivers): i82586.c
$(i82586_drivers): %.o: i82586.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(lance_drivers): lance.c
$(lance_drivers): %.o: lance.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(tulip_drivers): tulip.c
$(tulip_drivers): %.o: tulip.c
$(natsemi_drivers): natsemi.c
$(natsemi_drivers): %.o: natsemi.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(ni5010_drivers): ni5010.c
$(ni5010_drivers): %.o: ni5010.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(ns8390_drivers): ns8390.c ns8390.h
$(ns8390_drivers): %.o: ns8390.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -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 $<
@ -758,6 +935,11 @@ $(rtl8139_drivers): %.o: rtl8139.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(sis900_drivers): sis900.c
$(sis900_drivers): %.o: sis900.c sis900.h
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(sk_g16_drivers): sk_g16.c sk_g16.h
$(sk_g16_drivers): %.o: sk_g16.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
@ -773,8 +955,13 @@ $(tiara_drivers): %.o: tiara.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(otulip_drivers): otulip.c otulip.h
$(otulip_drivers): %.o: otulip.c
#$(tlan_drivers): tlan.c
#$(tlan_drivers): %.o: tlan.c
# $(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
# $(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(tulip_drivers): tulip.c
$(tulip_drivers): %.o: tulip.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
@ -782,6 +969,11 @@ $(via_rhine_drivers): via-rhine.c
$(via_rhine_drivers): %.o: via-rhine.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
$(w89c840_drivers): w89c840.c
$(w89c840_drivers): %.o: w89c840.c
$(COMPILE) $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
$(NET_EXTRAFLAGS) $($(basename $@)_o_CFLAGS) -o $@ -c $<
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View file

@ -31,29 +31,13 @@ Caution: You should enable them as you need. Don't enable any
unnecessary driver, because GRUB might crash if you include too many
drivers at the same time.
3Com503, aka Etherlink II, also /16 model
--enable-3c503
--enable-3c503-shmem
Use 3c503 shared memory mode.
--enable-3c503-aui
Use AUI by default on 3c503 cards.
3Com507
--enable-3c507
3Com509, ISA/EISA
--enable-3c509
--enable-3c509-hack
Send two bootp packets before waiting for a reply to the first.
Makes a 3c509 do bootp quicker.
3Com529 == MCA 3c509
--enable-3c529
3Com590
--enable-3c590
3Com595
3Com59x and 3Com900
--enable-3c595
3Com90x
@ -67,29 +51,52 @@ Crystal Semiconductor CS89x0
a more aggressive probing algorithm. This might be neccessary after
a soft-reset of the NIC.
Davicom DM9102 and 9009
--enable-davicom
Digital DE100 and DE200
--enable-depca
Intel Etherexpress Pro/10 (ISA card)
--enable-eepro
Intel Etherexpress Pro/100
--enable-eepro100
SMC 83c170 EPIC/100
--enable-epic100
3Com507
--enable-3c507
EXOS205
--enable-exos205
Racal-Interlan NI5210
--enable-ni5210
Lance PCI PCNet/32
AMD HomePNA
--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 ADMtek Centaur-P
Tulip clones based on the Macronix 987x5
Tulip-Fast
Tulip+
Tulip 21142
--enable-tulip
Novell NE2100 and NE1500
--enable-ne2100
Racal-Interlan NI6510
--enable-ni6510
National Semiconductor DP8381x (Netgear FA311 and FA312)
--enable-natsemi
Racal-Interlan NI5010
--enable-ni5010
3Com503, aka Etherlink II, also /16 model
--enable-3c503
--enable-3c503-shmem
Use 3c503 shared memory mode.
--enable-3c503-aui
Use AUI by default on 3c503 cards.
NE1000/2000 and clones (ISA)
--enable-ne
@ -97,35 +104,34 @@ NE1000/2000 and clones (ISA)
Probe for NE base address using LIST of comma separated hex
addresses.
Novell NE2100 (Lance based, also works on NE1500)
--enable-ne2100
NE2000 PCI clone (RTL8029)
Winbond 86C940
Compex RL2000
KTI ET32P2
NetVin 5000SC
Holtek 80232
--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
worked for me :).
--enable-ns8390-force-16bit
It seems that forcing 16 bit bus width for NEPCI causes
Etherboot/GRUB to fail on the RTL8029. Therefore
--enable-ns8390-force-16bit should only be turned on for those NEPCI
NICs that falsely detect 8 bit bus width when it should be 16.
Racal-Interlan NI5210
--enable-ni5210
WD8003/8013, SMC8216/8416
--enable-wd
--enable-wd-default-mem=MEM (0xCC000)
Default memory location for WD/SMC cards.
Racal-Interlan NI6510
--enable-ni6510
Old base driver for Tulip clones
--enable-otulip
Realtek 8139
SMC 1211
D-Link DFE530TX+ and DFE538TX
--enable-rtl8139
SIS 900 and SIS 7016
--enable-sis900
Schneider and Koch G16
--enable-sk-g16
@ -137,17 +143,25 @@ SMC9000
Tiara, Fujitsu Lancard
--enable-tiara
Old base driver for Tulip clones
--enable-otulip
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 ADMtek Centaur-P
Tulip clones based on the Macronix 987x5
Tulip-Fast
Tulip+
Tulip 21142
ASIX AX88140
Intel Tulip
Compex RL100-TX
--enable-tulip
Rhine-I, e.g. D-Link DFE-530TX
Rhine-II
--enable-via-rhine
WD8003/8013, SMC8216/8416
--enable-wd
--enable-wd-default-mem=MEM (0xCC000)
Default memory location for WD/SMC cards.
Winbond W89c840
Compex RL100-ATX
--enable-w89c840
The description about how to use the support can be found in the GRUB

View file

@ -65,6 +65,11 @@ extern struct nic *a3c90x_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_EEPRO
extern struct nic *eepro_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 *));
@ -85,6 +90,11 @@ extern struct nic *tulip_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_DAVICOM
extern struct nic *davicom_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 *));
@ -115,6 +125,11 @@ extern struct nic *t507_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_NI5010
extern struct nic *ni5010_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 *));
@ -145,4 +160,24 @@ extern struct nic *rtl8139_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_W89C840
extern struct nic *w89c840_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_SIS900
extern struct nic *sis900_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_NATSEMI
extern struct nic *natsemi_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#ifdef INCLUDE_TLAN
extern struct nic *tlan_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
#endif /* CARDS_H */

View file

@ -17,7 +17,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Based on "src/config.c" in etherboot-4.6.4. */
/* Based on "src/config.c" in etherboot-5.0.5. */
/*
* This program is free software; you can redistribute it and/or
@ -26,131 +26,206 @@
* your option) any later version.
*/
#include "etherboot.h"
#include "nic.h"
#define GRUB 1
#include <etherboot.h>
#include <nic.h>
#undef INCLUDE_PCI
#if defined(INCLUDE_NS8390) || defined(INCLUDE_EEPRO100) || defined(INCLUDE_LANCE) || defined(INCLUDE_EPIC100) || defined(INCLUDE_TULIP) || defined(INCLUDE_OTULIP) || defined(INCLUDE_3C90X) || defined(INCLUDE_3C595) || defined(INCLUDE_RTL8139) || defined(INCLUDE_VIA_RHINE)
#if defined(INCLUDE_NS8390) || defined(INCLUDE_EEPRO100) || defined(INCLUDE_LANCE) || defined(INCLUDE_EPIC100) || defined(INCLUDE_TULIP) || defined(INCLUDE_OTULIP) || defined(INCLUDE_3C90X) || defined(INCLUDE_3C595) || defined(INCLUDE_RTL8139) || defined(INCLUDE_VIA_RHINE) || defined(INCLUDE_W89C840) || defined(INCLUDE_DAVICOM) || defined(INCLUDE_SIS900) || defined(INCLUDE_NATSEMI) || defined(INCLUDE_TLAN)
/* || others later */
#if defined(ETHERBOOT32) /* only for 32 bit machines */
#define INCLUDE_PCI
#include "pci.h"
static unsigned short pci_ioaddrs[16];
# define INCLUDE_PCI
# include <pci.h>
static unsigned short pci_ioaddrs[16];
static struct pci_device pci_nic_list[] = {
static struct pci_device pci_nic_list[] =
{
#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,
"Winbond NE2000-PCI", 0, 0, 0},
{ PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000,
"Compex ReadyLink 2000", 0, 0, 0},
{ PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_ET32P2,
"KTI ET32P2", 0, 0, 0},
{ PCI_VENDOR_ID_NETVIN, PCI_DEVICE_ID_NETVIN_NV5000SC,
"NetVin NV5000SC", 0, 0, 0},
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029,
"Realtek 8029", 0, 0, 0, 0},
{ PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940,
"Winbond NE2000-PCI", 0, 0, 0, 0},
{ PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000,
"Compex ReadyLink 2000", 0, 0, 0, 0},
{ PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_ET32P2,
"KTI ET32P2", 0, 0, 0, 0},
{ PCI_VENDOR_ID_NETVIN, PCI_DEVICE_ID_NETVIN_NV5000SC,
"NetVin NV5000SC", 0, 0, 0, 0},
{ PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_HT80232,
"Holtek HT80232", 0, 0, 0, 0},
#endif
#ifdef INCLUDE_3C90X
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900TPO,
"3Com900-TPO", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900COMBO,
"3Com900-Combo", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905TX,
"3Com905-TX", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905T4,
"3Com905-T4", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9004,
"3Com900B-TPO", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9005,
"3Com900B-Combo", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9006,
"3Com900B-2/T", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x900A,
"3Com900B-FL", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905B_TX,
"3Com905B-TX", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9056,
"3Com905B-T4", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x905A,
"3Com905B-FL", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905C_TXM,
"3Com905C-TXM", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900TPO,
"3Com900-TPO", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900COMBO,
"3Com900-Combo", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905TX,
"3Com905-TX", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905T4,
"3Com905-T4", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9004,
"3Com900B-TPO", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9005,
"3Com900B-Combo", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9006,
"3Com900B-2/T", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x900A,
"3Com900B-FL", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905B_TX,
"3Com905B-TX", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9056,
"3Com905B-T4", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x905A,
"3Com905B-FL", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905C_TXM,
"3Com905C-TXM", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9800,
"3Com980-Cyclone", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9805,
"3Com9805", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x7646,
"3CSOHO100-TX", 0, 0, 0, 0},
#endif
#ifdef INCLUDE_3C595
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C590,
"3Com590", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595,
"3Com595", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595_1,
"3Com595", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595_2,
"3Com595", 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C590,
"3Com590", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595,
"3Com595", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595_1,
"3Com595", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595_2,
"3Com595", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900TPO,
"3Com900-TPO", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900COMBO,
"3Com900-Combo", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9004,
"3Com900B-TPO", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9005,
"3Com900B-Combo", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9006,
"3Com900B-2/T", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x900A,
"3Com900B-FL", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9800,
"3Com980-Cyclone", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x9805,
"3Com9805", 0, 0, 0, 0},
{ PCI_VENDOR_ID_3COM, 0x7646,
"3CSOHO100-TX", 0, 0, 0, 0},
#endif
#ifdef INCLUDE_EEPRO100
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
"Intel EtherExpressPro100", 0, 0, 0},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
"Intel EtherExpressPro100", 0, 0, 0, 0},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER,
"Intel EtherExpressPro100 82559ER", 0, 0, 0, 0},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1029,
"Intel EtherExpressPro100 ID1029", 0, 0, 0, 0},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1030,
"Intel Corporation 82559 InBusiness 10/100", 0, 0, 0, 0},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82562,
"Intel EtherExpressPro100 82562EM", 0, 0, 0, 0},
#endif
#ifdef INCLUDE_EPIC100
{ PCI_VENDOR_ID_SMC, PCI_DEVICE_ID_SMC_EPIC100,
"SMC EtherPowerII", 0, 0, 0},
{ PCI_VENDOR_ID_SMC, PCI_DEVICE_ID_SMC_EPIC100,
"SMC EtherPowerII", 0, 0, 0, 0},
#endif
#ifdef INCLUDE_LANCE
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
"AMD Lance/PCI", 0, 0, 0},
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
"AMD Lance/PCI", 0, 0, 0, 0},
{ PCI_VENDOR_ID_AMD_HOMEPNA, PCI_DEVICE_ID_AMD_HOMEPNA,
"AMD Lance/HomePNA", 0, 0, 0, 0},
#endif
#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},
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
"Realtek 8139", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DFE530TXP,
"DFE530TX+/DFE538TX", 0, 0, 0, 0},
{ PCI_VENDOR_ID_SMC_1211, PCI_DEVICE_ID_SMC_1211,
"SMC EZ10/100", 0, 0, 0, 0},
#endif
#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,
"Digital Tulip Fast", 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
"Digital Tulip+", 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
"Digital Tulip 21142", 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
"Digital Tulip", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
"Digital Tulip Fast", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
"Digital Tulip+", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
"Digital Tulip 21142", 0, 0, 0, 0},
#endif
#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,
"Digital Tulip Fast", 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
"Digital Tulip+", 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
"Digital Tulip 21142", 0, 0, 0},
{ PCI_VENDOR_ID_MACRONIX, PCI_DEVICE_ID_MX987x5,
"Macronix MX987x5", 0, 0, 0},
{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LC82C115,
"LinkSys LNE100TX", 0, 0, 0},
{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_DEC_TULIP,
"Netgear FA310TX", 0, 0, 0},
{ PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DM9102,
"Davicom 9102", 0, 0, 0},
{ PCI_VENDOR_ID_ADMTEK, PCI_DEVICE_ID_ADMTEK_0985,
"ADMtek Centaur-P", 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
"Digital Tulip", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
"Digital Tulip Fast", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
"Digital Tulip+", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
"Digital Tulip 21142", 0, 0, 0, 0},
{ PCI_VENDOR_ID_MACRONIX, PCI_DEVICE_ID_MX987x5,
"Macronix MX987x5", 0, 0, 0, 0},
{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LC82C115,
"LinkSys LNE100TX", 0, 0, 0, 0},
{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_DEC_TULIP,
"Netgear FA310TX", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DM9102,
"Davicom 9102", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DM9009,
"Davicom 9009", 0, 0, 0, 0},
{ PCI_VENDOR_ID_ADMTEK, PCI_DEVICE_ID_ADMTEK_0985,
"ADMtek Centaur-P", 0, 0, 0, 0},
{ PCI_VENDOR_ID_ADMTEK, 0x0981,
"ADMtek AN981 Comet", 0, 0, 0, 0},
{ 0x125B, 0x1400,
"ASIX AX88140", 0, 0, 0, 0 },
{ 0x11F6, 0x9881,
"Compex RL100-TX", 0, 0, 0, 0 },
#endif
#ifdef INCLUDE_DAVICOM
{ PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DM9102,
"Davicom 9102", 0, 0, 0, 0},
{ PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DM9009,
"Davicom 9009", 0, 0, 0, 0},
#endif
#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},
{ PCI_VENDOR_ID_VIATEC, PCI_DEVICE_ID_VIA_VT6102,
"VIA 6102", 0, 0, 0, 0},
{ PCI_VENDOR_ID_VIATEC, PCI_DEVICE_ID_VIA_RHINE_I,
"VIA 3043", 0, 0, 0, 0},
{ PCI_VENDOR_ID_VIATEC, PCI_DEVICE_ID_VIA_86C100A,
"VIA 86C100A", 0, 0, 0, 0},
#endif
/* other PCI NICs go here */
{0, 0, NULL, 0, 0, 0}
#ifdef INCLUDE_W89C840
{ PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C840,
"Winbond W89C840F", 0, 0, 0, 0},
{ PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL100ATX,
"Compex RL100ATX", 0, 0, 0, 0},
#endif
#ifdef INCLUDE_SIS900
{ PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900,
"SIS900", 0, 0, 0, 0},
{ PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016,
"SIS7016", 0, 0, 0, 0},
#endif
#ifdef INCLUDE_NATSEMI
{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_DP83815,
"DP83815", 0, 0, 0, 0},
#endif
#ifdef INCLUDE_TLAN
{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2326,
"OC2326", 0, 0, 0, 0},
#endif
/* other PCI NICs go here */
{0, 0, NULL, 0, 0, 0, 0}
};
#endif /* ETHERBOOT32 */
#endif /* INCLUDE_*PCI */
#include "cards.h"
#include <cards.h>
#if defined(GRUB) && defined(INCLUDE_PCI)
#ifdef INCLUDE_PCI
struct pci_dispatch_table
{
unsigned short vendor;
@ -167,6 +242,7 @@ static struct pci_dispatch_table PCI_NIC[] =
{ PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000, nepci_probe },
{ PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_ET32P2, nepci_probe },
{ PCI_VENDOR_ID_NETVIN, PCI_DEVICE_ID_NETVIN_NV5000SC, nepci_probe },
{ PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_HT80232, nepci_probe },
# endif /* INCLUDE_NS8390 */
# ifdef INCLUDE_3C90X
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900TPO, a3c90x_probe },
@ -181,24 +257,42 @@ static struct pci_dispatch_table PCI_NIC[] =
{ PCI_VENDOR_ID_3COM, 0x9056, a3c90x_probe },
{ PCI_VENDOR_ID_3COM, 0x905A, a3c90x_probe },
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C905C_TXM, a3c90x_probe },
{ PCI_VENDOR_ID_3COM, 0x9800, a3c90x_probe },
{ PCI_VENDOR_ID_3COM, 0x9805, a3c90x_probe },
{ PCI_VENDOR_ID_3COM, 0x7646, a3c90x_probe },
# endif /* INCLUDE_3C90X */
# ifdef INCLUDE_3C595
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C590, t595_probe },
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595, t595_probe },
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595_1, t595_probe },
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C595_2, t595_probe },
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900TPO, t595_probe },
{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C900COMBO, t595_probe },
{ PCI_VENDOR_ID_3COM, 0x9004, t595_probe },
{ PCI_VENDOR_ID_3COM, 0x9005, t595_probe },
{ PCI_VENDOR_ID_3COM, 0x9006, t595_probe },
{ PCI_VENDOR_ID_3COM, 0x900A, t595_probe },
{ PCI_VENDOR_ID_3COM, 0x9800, t595_probe },
{ PCI_VENDOR_ID_3COM, 0x9805, t595_probe },
{ PCI_VENDOR_ID_3COM, 0x7646, t595_probe },
# endif /* INCLUDE_3C595 */
# ifdef INCLUDE_EEPRO100
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557, eepro100_probe },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER, eepro100_probe },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1029, eepro100_probe },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1030, eepro100_probe },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82562, eepro100_probe },
# endif /* INCLUDE_EEPRO100 */
# ifdef INCLUDE_EPIC100
{ PCI_VENDOR_ID_SMC, PCI_DEVICE_ID_SMC_EPIC100, epic100_probe },
# endif /* INCLUDE_EPIC100 */
# ifdef INCLUDE_LANCE
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, lancepci_probe },
{ PCI_VENDOR_ID_AMD_HOMEPNA, PCI_DEVICE_ID_AMD_HOMEPNA, lancepci_probe },
# endif /* INCLUDE_LANCE */
# ifdef INCLUDE_RTL8139
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139, rtl8139_probe },
{ PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DFE530TXP, rtl8139_probe },
{ PCI_VENDOR_ID_SMC_1211, PCI_DEVICE_ID_SMC_1211, rtl8139_probe },
# endif /* INCLUDE_RTL8139 */
# ifdef INCLUDE_OTULIP
@ -216,26 +310,49 @@ static struct pci_dispatch_table PCI_NIC[] =
{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LC82C115, tulip_probe },
{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_DEC_TULIP, tulip_probe },
{ PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DM9102, tulip_probe },
{ PCI_VENDOR_ID_DAVICOM, PCI_DEVICE_ID_DM9009, tulip_probe },
{ PCI_VENDOR_ID_ADMTEK, PCI_DEVICE_ID_ADMTEK_0985, tulip_probe },
{ PCI_VENDOR_ID_ADMTEK, 0x0981, tulip_probe },
{ 0x125B, 0x1400, tulip_probe },
{ 0x11F6, 0x9881, tulip_probe },
# endif /* INCLUDE_TULIP */
# ifdef INCLUDE_DAVICOM
{ PC_VENDOR_ID_DAVICOM, PC_DEVICE_ID_DM9102, davicom_probe },
{ PC_VENDOR_ID_DAVICOM, PC_DEVICE_ID_DM9009, davicom_probe },
# endif /* INCLUDE_DAVICOM */
# ifdef INCLUDE_VIA_RHINE
{ PCI_VENDOR_ID_VIATEC, PCI_DEVICE_ID_VIA_VT6102, rhine_probe },
{ PCI_VENDOR_ID_VIATEC, PCI_DEVICE_ID_VIA_RHINE_I, rhine_probe },
{ PCI_VENDOR_ID_VIATEC, PCI_DEVICE_ID_VIA_86C100A, rhine_probe },
# endif /* INCLUDE_VIA_RHINE */
# ifdef INCLUDE_W89C840
{ PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C840, w89c840_probe },
{ PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL100ATX, w89c840_probe },
# endif /* INCLUDE_W89C840 */
# ifdef INCLUDE_SIS900
{ PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900, sis900_probe },
{ PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016, sis900_probe },
# endif /* INCLUDE_SIS900 */
# ifdef INCLUDE_NATSEMI
{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_DP83815, natsemi_probe },
# endif /* INCLUDE_NATSEMI */
# ifdef INCLUDE_TLAN
{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2326, tlan_probe },
# endif /* INCLUDE_TLAN */
{ 0, 0, 0 }
};
#endif /* GRUB && INCLUDE_PCI */
struct dispatch_table
{
const char *nic_name;
const char *nic_name;
#ifdef INCLUDE_PCI
struct nic *(*eth_probe)(struct nic *, unsigned short *,
struct pci_device *);
struct nic *(*eth_probe) (struct nic *, unsigned short *,
struct pci_device *);
#else
struct nic *(*eth_probe)(struct nic *, unsigned short *);
struct nic *(*eth_probe) (struct nic *, unsigned short *);
#endif /* INCLUDE_PCI */
unsigned short *probe_ioaddrs; /* for probe overrides */
unsigned short *probe_ioaddrs; /* for probe overrides */
};
/*
@ -246,233 +363,236 @@ struct dispatch_table
static struct dispatch_table NIC[] =
{
#ifdef INCLUDE_RTL8139
{ "RTL8139", rtl8139_probe, pci_ioaddrs },
{ "RTL8139", rtl8139_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_SIS900
{ "SIS900", sis900_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_NATSEMI
{ "NATSEMI", natsemi_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_WD
{ "WD", wd_probe, 0 },
{ "WD", wd_probe, 0 },
#endif
#ifdef INCLUDE_3C503
{ "3C503", t503_probe, 0 },
{ "3C503", t503_probe, 0 },
#endif
#ifdef INCLUDE_NE
{ "NE*000", ne_probe, 0 },
{ "NE*000", ne_probe, 0 },
#endif
#ifdef INCLUDE_3C509
{ "3C5x9", t509_probe, 0 },
{ "3C5x9", t509_probe, 0 },
#endif
#ifdef INCLUDE_3C529
{ "3C5x9", t529_probe, 0 },
{ "3C5x9", t529_probe, 0 },
#endif
#ifdef INCLUDE_3C595
{ "3C595", t595_probe, pci_ioaddrs },
{ "3C595", t595_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_3C90X
{ "3C90X", a3c90x_probe, pci_ioaddrs },
{ "3C90X", a3c90x_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_EEPRO
{ "EEPRO", eepro_probe, 0 },
#endif
#ifdef INCLUDE_EEPRO100
{ "EEPRO100", eepro100_probe, pci_ioaddrs },
{ "EEPRO100", eepro100_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_EPIC100
{ "EPIC100", epic100_probe, pci_ioaddrs },
{ "EPIC100", epic100_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_OTULIP
{ "OTulip", otulip_probe, pci_ioaddrs },
{ "OTulip", otulip_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_TULIP
{ "Tulip", tulip_probe, pci_ioaddrs },
{ "Tulip", tulip_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_DAVICOM
{ "DAVICOM", davicom_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_CS89X0
{ "CS89x0", cs89x0_probe, 0 },
{ "CS89x0", cs89x0_probe, 0 },
#endif
#ifdef INCLUDE_NE2100
{ "NE2100", ne2100_probe, 0 },
{ "NE2100", ne2100_probe, 0 },
#endif
#ifdef INCLUDE_NI6510
{ "NI6510", ni6510_probe, 0 },
{ "NI6510", ni6510_probe, 0 },
#endif
#ifdef INCLUDE_SK_G16
{ "SK_G16", SK_probe, 0 },
{ "SK_G16", SK_probe, 0 },
#endif
#ifdef INCLUDE_3C507
{ "3C507", t507_probe, 0 },
{ "3C507", t507_probe, 0 },
#endif
#ifdef INCLUDE_NI5010
{ "NI5010", ni5010_probe, 0 },
#endif
#ifdef INCLUDE_NI5210
{ "NI5210", ni5210_probe, 0 },
{ "NI5210", ni5210_probe, 0 },
#endif
#ifdef INCLUDE_EXOS205
{ "EXOS205", exos205_probe, 0 },
{ "EXOS205", exos205_probe, 0 },
#endif
#ifdef INCLUDE_SMC9000
{ "SMC9000", smc9000_probe, 0 },
{ "SMC9000", smc9000_probe, 0 },
#endif
#ifdef INCLUDE_TIARA
{ "TIARA", tiara_probe, 0 },
{ "TIARA", tiara_probe, 0 },
#endif
#ifdef INCLUDE_DEPCA
{ "DEPCA", depca_probe, 0 },
{ "DEPCA", depca_probe, 0 },
#endif
#ifdef INCLUDE_NS8390
{ "NE2000/PCI", nepci_probe, pci_ioaddrs },
{ "NE2000/PCI", nepci_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_LANCE
{ "LANCE/PCI", lancepci_probe, pci_ioaddrs },
{ "LANCE/PCI", lancepci_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_VIA_RHINE
{ "VIA 86C100", rhine_probe, pci_ioaddrs },
{ "VIA 86C100", rhine_probe, pci_ioaddrs },
#endif
/* this entry must always be last to mark the end of list */
{ 0, 0, 0 }
#ifdef INCLUDE_W89C840
{ "W89C840F", w89c840_probe, pci_ioaddrs },
#endif
#ifdef INCLUDE_TLAN
{ "Olicom 2326", tlan_probe, pci_ioaddrs },
#endif
/* this entry must always be last to mark the end of list */
{ 0, 0, 0 }
};
#define NIC_TABLE_SIZE (sizeof(NIC)/sizeof(NIC[0]))
#define NIC_TABLE_SIZE (sizeof (NIC) / sizeof (NIC[0]))
static int eth_dummy(struct nic *nic)
static int
eth_dummy (struct nic *dummy)
{
return (0);
return 0;
}
static char packet[ETH_MAX_PACKET];
static char packet[ETH_FRAME_LEN];
struct nic nic =
{
#ifdef ETHERBOOT32
(void (*)(struct nic *))eth_dummy, /* reset */
eth_dummy, /* poll */
(void (*)(struct nic *, const char *,
unsigned int, unsigned int,
const char *))eth_dummy, /* transmit */
(void (*)(struct nic *))eth_dummy, /* disable */
#endif
/* bcc has problems with complicated casts */
#ifdef ETHERBOOT16
eth_dummy,
eth_dummy,
eth_dummy,
eth_dummy,
#endif
(void (*) (struct nic *)) eth_dummy, /* reset */
eth_dummy, /* poll */
(void (*) (struct nic *, const char *,
unsigned int, unsigned int,
const char *)) eth_dummy, /* transmit */
(void (*) (struct nic *)) eth_dummy, /* disable */
#ifdef T503_AUI
1, /* aui */
1, /* aui */
#else
0, /* no aui */
0, /* no aui */
#endif
arptable[ARP_CLIENT].node, /* node_addr */
packet, /* packet */
0, /* packetlen */
0 /* priv_data */
&rom, /* rom_info */
arptable[ARP_CLIENT].node, /* node_addr */
packet, /* packet */
0, /* packetlen */
0, /* priv_data */
};
#ifndef GRUB
void print_config(void)
void
eth_reset (void)
{
struct dispatch_table *t;
#ifdef ETHERBOOT32
printf("Etherboot/32 version " VERSION " (GPL) for ");
#endif
#ifdef ETHERBOOT16
/* Must be all on line or bcc can't handle concatenation */
printf("Etherboot/16 version " VERSION " (GPL) for ");
#endif
for (t = NIC; t->nic_name != 0; ++t)
printf("[%s]", t->nic_name);
putchar('\n');
}
#endif /* ! GRUB */
void eth_reset(void)
{
(*nic.reset)(&nic);
(*nic.reset) (&nic);
}
int eth_probe(void)
int
eth_probe (void)
{
struct pci_device *p;
struct dispatch_table *t;
#ifdef GRUB
static int probed = 0;
#endif /* GRUB */
struct pci_device *p;
const struct dispatch_table *t;
static int probed = 0;
#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));
#endif /* GRUB */
p = 0;
/* 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));
p = 0;
#ifdef INCLUDE_PCI
# 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
we just pick the first one with a non-zero ioaddr */
for (p = pci_nic_list; p->vendor != 0; ++p) {
if (p->ioaddr != 0) {
pci_ioaddrs[0] = p->ioaddr;
break;
}
}
#endif
printf("Probing...");
#if defined(GRUB) && defined(INCLUDE_PCI)
if (p->vendor)
{
struct pci_dispatch_table *pt;
for (pt = PCI_NIC; pt->eth_probe != 0; pt++)
if (p->vendor == pt->vendor && p->dev_id == pt->dev_id)
{
printf ("[%s]", p->name);
if ((pt->eth_probe) (&nic, pci_ioaddrs, p))
{
probed = 1;
return 1;
}
}
}
#endif /* GRUB && INCLUDE_PCI */
for (t = NIC; t->nic_name != 0; ++t)
/* In GRUB, the ROM info is initialized here. */
rom = *((struct rom_info *) ROM_INFO_LOCATION);
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
we just pick the first one with a non-zero ioaddr */
for (p = pci_nic_list; p->vendor != 0; ++p)
{
if (p->ioaddr != 0)
{
printf("[%s]", t->nic_name);
#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);
}
pci_ioaddrs[0] = p->ioaddr;
break;
}
return (0);
}
#endif
etherboot_printf("Probing...");
#ifdef INCLUDE_PCI
if (p->vendor)
{
struct pci_dispatch_table *pt;
for (pt = PCI_NIC; pt->eth_probe != 0; pt++)
if (p->vendor == pt->vendor && p->dev_id == pt->dev_id)
{
etherboot_printf ("[%s]", p->name);
if ((pt->eth_probe) (&nic, pci_ioaddrs, p))
{
probed = 1;
return 1;
}
}
}
#endif /* INCLUDE_PCI */
for (t = NIC; t->nic_name != 0; ++t)
{
etherboot_printf("[%s]", t->nic_name);
#ifdef INCLUDE_PCI
if ((*t->eth_probe) (&nic, t->probe_ioaddrs, p))
{
probed = 1;
return 1;
}
#else
if ((*t->eth_probe) (&nic, t->probe_ioaddrs))
{
probed = 1;
return 1;
}
#endif /* INCLUDE_PCI */
}
return 0;
}
int eth_poll(void)
int
eth_poll (void)
{
return ((*nic.poll)(&nic));
return ((*nic.poll) (&nic));
}
void eth_transmit(const char *d, unsigned int t, unsigned int s, const void *p)
void
eth_transmit (const char *d, unsigned int t, unsigned int s, const void *p)
{
(*nic.transmit)(&nic, d, t, s, p);
twiddle();
(*nic.transmit) (&nic, d, t, s, p);
if (t == IP)
twiddle ();
}
void eth_disable(void)
void
eth_disable (void)
{
(*nic.disable)(&nic);
(*nic.disable) (&nic);
}

View file

@ -75,7 +75,6 @@ static unsigned short eth_cs_type; /* one of: CS8900, CS8920, CS8920M */
static unsigned short eth_auto_neg_cnf;
static unsigned short eth_adapter_cnf;
static unsigned short eth_linectl;
static unsigned char eth_vendor;
/*************************************************************************
CS89x0 - specific routines
@ -116,7 +115,7 @@ static int get_eeprom_data(int off, int len, unsigned short *buffer)
int i;
#ifdef EDEBUG
printf("\ncs: EEPROM data from %x for %x:",off,len);
printf("\ncs: EEPROM data from %hX for %hX:",off,len);
#endif
for (i = 0; i < len; i++) {
if (wait_eeprom_ready() < 0)
@ -130,7 +129,7 @@ static int get_eeprom_data(int off, int len, unsigned short *buffer)
#ifdef EDEBUG
if (!(i%10))
printf("\ncs: ");
printf("%x ", buffer[i]);
printf("%hX ", buffer[i]);
#endif
}
#ifdef EDEBUG
@ -235,7 +234,7 @@ static int detect_tp(void)
/* send a test packet - return true if carrier bits are ok */
static int send_test_pkt(struct nic *nic)
{
static char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
static unsigned char testpacket[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
0, 46, /*A 46 in network order */
0, 0, /*DSAP=0 & SSAP=0 fields */
0xf3,0 /*Control (Test Req+P bit set)*/ };
@ -243,11 +242,11 @@ static int send_test_pkt(struct nic *nic)
writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_TX_ON);
memcpy(testpacket, nic->node_addr, ETHER_ADDR_SIZE);
memcpy(testpacket+ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE);
memcpy(testpacket, nic->node_addr, ETH_ALEN);
memcpy(testpacket+ETH_ALEN, nic->node_addr, ETH_ALEN);
outw(TX_AFTER_ALL, eth_nic_base + TX_CMD_PORT);
outw(ETH_MIN_PACKET, eth_nic_base + TX_LEN_PORT);
outw(ETH_ZLEN, eth_nic_base + TX_LEN_PORT);
/* Test to see if the chip has allocated memory for the packet */
for (tmo = currticks() + 2;
@ -257,7 +256,7 @@ static int send_test_pkt(struct nic *nic)
/* Write the contents of the packet */
outsw(eth_nic_base + TX_FRAME_PORT, testpacket,
(ETH_MIN_PACKET+1)>>1);
(ETH_ZLEN+1)>>1);
printf(" sending test packet ");
/* wait a couple of timer ticks for packet to be received */
@ -307,9 +306,6 @@ static void cs89x0_reset(struct nic *nic)
int i;
unsigned long reset_tmo;
if(eth_vendor!=VENDOR_CS89x0)
return;
writereg(PP_SelfCTL, readreg(PP_SelfCTL) | POWER_ON_RESET);
/* wait for two ticks; that is 2*55ms */
@ -337,7 +333,7 @@ static void cs89x0_reset(struct nic *nic)
writereg(PP_BusCTL, 0);
/* set the ethernet address */
for (i=0; i < ETHER_ADDR_SIZE/2; i++)
for (i=0; i < ETH_ALEN/2; i++)
writereg(PP_IA+i*2,
nic->node_addr[i*2] |
(nic->node_addr[i*2+1] << 8));
@ -374,13 +370,10 @@ static void cs89x0_transmit(
unsigned long tmo;
int sr;
if(eth_vendor!=VENDOR_CS89x0)
return;
/* does this size have to be rounded??? please,
somebody have a look in the specs */
if ((sr = ((s + ETHER_HDR_SIZE + 1)&~1)) < ETH_MIN_PACKET)
sr = ETH_MIN_PACKET;
if ((sr = ((s + ETH_HLEN + 1)&~1)) < ETH_ZLEN)
sr = ETH_ZLEN;
retry:
/* initiate a transmit sequence */
@ -396,12 +389,12 @@ retry:
goto retry; }
/* Write the contents of the packet */
outsw(eth_nic_base + TX_FRAME_PORT, d, ETHER_ADDR_SIZE/2);
outsw(eth_nic_base + TX_FRAME_PORT, d, ETH_ALEN/2);
outsw(eth_nic_base + TX_FRAME_PORT, nic->node_addr,
ETHER_ADDR_SIZE/2);
ETH_ALEN/2);
outw(((t >> 8)&0xFF)|(t << 8), eth_nic_base + TX_FRAME_PORT);
outsw(eth_nic_base + TX_FRAME_PORT, p, (s+1)/2);
for (sr = sr/2 - (s+1)/2 - ETHER_ADDR_SIZE - 1; sr-- > 0;
for (sr = sr/2 - (s+1)/2 - ETH_ALEN - 1; sr-- > 0;
outw(0, eth_nic_base + TX_FRAME_PORT));
/* wait for transfer to succeed */
@ -409,7 +402,7 @@ retry:
(s = readreg(PP_TxEvent)&~0x1F) == 0 && currticks() < tmo;)
/* nothing */ ;
if ((s & TX_SEND_OK_BITS) != TX_OK) {
printf("\ntransmission error 0x%x\n", s);
printf("\ntransmission error %#hX\n", s);
}
return;
@ -423,9 +416,6 @@ static int cs89x0_poll(struct nic *nic)
{
int status;
if(eth_vendor!=VENDOR_CS89x0)
return 0;
status = readreg(PP_RxEvent);
if ((status & RX_OK) == 0)
@ -441,6 +431,7 @@ static int cs89x0_poll(struct nic *nic)
static void cs89x0_disable(struct nic *nic)
{
cs89x0_reset(nic);
}
/**************************************************************************
@ -466,9 +457,7 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
unsigned short eeprom_buff[CHKSUM_LEN];
for (eth_vendor = VENDOR_NONE, ioidx = 0;
eth_vendor == VENDOR_NONE &&
(ioaddr=netcard_portlist[ioidx++]) != 0;) {
for (ioidx = 0; (ioaddr=netcard_portlist[ioidx++]) != 0; ) {
/* if they give us an odd I/O address, then do ONE write to
the address port, to get it back to address zero, where we
expect to find the EISA signature word. */
@ -488,7 +477,7 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
eth_cs_type = rev_type &~ REVISON_BITS;
cs_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
printf("\ncs: cs89%c0%s rev %c, base 0x%x",
printf("\ncs: cs89%c0%s rev %c, base %#hX",
eth_cs_type==CS8900?'0':'2',
eth_cs_type==CS8920M?"M":"",
cs_revision,
@ -548,10 +537,10 @@ 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++) {
printf("%b%s",(int)(nic->node_addr[i] =
((unsigned char *)eeprom_buff)[i]),
i < ETHER_ADDR_SIZE-1 ? ":" : "\n"); }
for (i=0; i<ETH_ALEN; i++) {
nic->node_addr[i] = ((unsigned char *)eeprom_buff)[i];
}
printf("%!\n", nic->node_addr);
/* Set the LineCTL quintuplet based on adapter
configuration read from EEPROM */
@ -583,9 +572,7 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
}
/* Initialize the card for probing of the attached media */
eth_vendor = VENDOR_CS89x0;
cs89x0_reset(nic);
eth_vendor = VENDOR_NONE;
/* set the hardware to the configured choice */
switch(eth_adapter_cnf & A_CNF_MEDIA_TYPE) {
@ -652,14 +639,16 @@ struct nic *cs89x0_probe(struct nic *nic, unsigned short *probe_addrs)
writereg(PP_LineCTL, readreg(PP_LineCTL) | SERIAL_RX_ON |
SERIAL_TX_ON);
eth_vendor = VENDOR_CS89x0;
break;
}
if (ioaddr == 0)
return (0);
nic->reset = cs89x0_reset;
nic->poll = cs89x0_poll;
nic->transmit = cs89x0_transmit;
nic->disable = cs89x0_disable;
return nic;
return (nic);
}
/*

692
netboot/davicom.c Normal file
View file

@ -0,0 +1,692 @@
/*
DAVICOM DM9009/DM9102/DM9102A Etherboot Driver V1.00
This driver was ported from Marty Conner's Tulip Etherboot driver.
Thanks Marty Connor (mdc@thinguin.org)
You can get Tulip driver source file from this URL:
"http://etherboot.sourceforge..net/#Distribution"
This davicom etherboot driver supports DM9009/DM9102/DM9102A/
DM9102A+DM9801/DM9102A+DM9802 NICs.
This software may be used and distributed according to the terms
of the GNU Public License, incorporated herein by reference.
*/
/*********************************************************************/
/* Revision History */
/*********************************************************************/
/*
19 OCT 2000 Sten 1.00
Different half and full duplex mode
Do the different programming for DM9801/DM9802
12 OCT 2000 Sten 0.90
This driver was ported from tulip driver and it
has the following difference.
Changed symbol tulip/TULIP to davicom/DAVICOM
Deleted some code that did not use in this driver.
Used chain-strcture to replace ring structure
for both TX/RX descriptor.
Allocated two tx descriptor.
According current media mode to set operating
register(CR6)
*/
/*********************************************************************/
/* Declarations */
/*********************************************************************/
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#include "cards.h"
#undef DAVICOM_DEBUG
#undef DAVICOM_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 davicom device */
enum davicom_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
};
/* EEPROM Address width definitions */
#define EEPROM_ADDRLEN 6
#define EEPROM_SIZE 32 /* 1 << EEPROM_ADDRLEN */
/* Used to be 128, but we only need to read enough to get the MAC
address at bytes 20..25 */
/* 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)
/* Sten 10/11 for phyxcer */
#define PHY_DATA_0 0x0
#define PHY_DATA_1 0x20000
#define MDCLKH 0x10000
/* 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 long ioaddr;
/* Note: transmit and receive buffers must be longword aligned and
longword divisable */
/* transmit descriptor and buffer */
#define NTXD 2
static struct txdesc txd[NTXD] __attribute__ ((aligned(4)));
#ifdef USE_LOWMEM_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 rxdesc rxd[NRXD] __attribute__ ((aligned(4)));
#ifdef USE_LOWMEM_BUFFER
#define rxb ((char *)0x10000 - NRXD * BUFLEN - BUFLEN)
#else
static unsigned char rxb[NRXD * BUFLEN] __attribute__ ((aligned(4)));
#endif
static int rxd_tail;
static int TxPtr;
/*********************************************************************/
/* Function Prototypes */
/*********************************************************************/
static void whereami(const char *str);
static int read_eeprom(unsigned long ioaddr, int location, int addr_len);
struct nic *davicom_probe(struct nic *nic, unsigned short *io_addrs,
struct pci_device *pci);
static void davicom_init_chain(struct nic *nic); /* Sten 10/9 */
static void davicom_reset(struct nic *nic);
static void davicom_transmit(struct nic *nic, const char *d, unsigned int t,
unsigned int s, const char *p);
static int davicom_poll(struct nic *nic);
static void davicom_disable(struct nic *nic);
static void whereami (const char *str);
#ifdef DAVICOM_DEBUG
static void davicom_more(void);
#endif /* DAVICOM_DEBUG */
static void davicom_wait(unsigned int nticks);
static int phy_read(int);
static void phy_write(int, u16);
static void phy_write_1bit(u32, u32);
static int phy_read_1bit(u32);
static void davicom_media_chk(struct nic *);
/*********************************************************************/
/* Utility Routines */
/*********************************************************************/
static inline void whereami (const char *str)
{
#ifdef DAVICOM_DEBUG_WHERE
printf("%s\n", str);
/* sleep(2); */
#endif
}
#ifdef DAVICOM_DEBUG
static void davicom_more()
{
printf("\n\n-- more --");
while (!iskey())
/* wait */;
getchar();
printf("\n\n");
}
#endif /* DAVICOM_DEBUG */
static void davicom_wait(unsigned int nticks)
{
unsigned int to = currticks() + nticks;
while (currticks() < to)
/* wait */ ;
}
/*********************************************************************/
/* For DAVICOM phyxcer register by MII interface */
/*********************************************************************/
/*
Read a word data from phy register
*/
static int phy_read(int location)
{
int i, phy_addr=1;
u16 phy_data;
u32 io_dcr9;
whereami("phy_read\n");
io_dcr9 = ioaddr + CSR9;
/* Send 33 synchronization clock to Phy controller */
for (i=0; i<34; i++)
phy_write_1bit(io_dcr9, PHY_DATA_1);
/* Send start command(01) to Phy */
phy_write_1bit(io_dcr9, PHY_DATA_0);
phy_write_1bit(io_dcr9, PHY_DATA_1);
/* Send read command(10) to Phy */
phy_write_1bit(io_dcr9, PHY_DATA_1);
phy_write_1bit(io_dcr9, PHY_DATA_0);
/* Send Phy addres */
for (i=0x10; i>0; i=i>>1)
phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0);
/* Send register addres */
for (i=0x10; i>0; i=i>>1)
phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0);
/* Skip transition state */
phy_read_1bit(io_dcr9);
/* read 16bit data */
for (phy_data=0, i=0; i<16; i++) {
phy_data<<=1;
phy_data|=phy_read_1bit(io_dcr9);
}
return phy_data;
}
/*
Write a word to Phy register
*/
static void phy_write(int location, u16 phy_data)
{
u16 i, phy_addr=1;
u32 io_dcr9;
whereami("phy_write\n");
io_dcr9 = ioaddr + CSR9;
/* Send 33 synchronization clock to Phy controller */
for (i=0; i<34; i++)
phy_write_1bit(io_dcr9, PHY_DATA_1);
/* Send start command(01) to Phy */
phy_write_1bit(io_dcr9, PHY_DATA_0);
phy_write_1bit(io_dcr9, PHY_DATA_1);
/* Send write command(01) to Phy */
phy_write_1bit(io_dcr9, PHY_DATA_0);
phy_write_1bit(io_dcr9, PHY_DATA_1);
/* Send Phy addres */
for (i=0x10; i>0; i=i>>1)
phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0);
/* Send register addres */
for (i=0x10; i>0; i=i>>1)
phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0);
/* written trasnition */
phy_write_1bit(io_dcr9, PHY_DATA_1);
phy_write_1bit(io_dcr9, PHY_DATA_0);
/* Write a word data to PHY controller */
for (i=0x8000; i>0; i>>=1)
phy_write_1bit(io_dcr9, phy_data&i ? PHY_DATA_1: PHY_DATA_0);
}
/*
Write one bit data to Phy Controller
*/
static void phy_write_1bit(u32 ee_addr, u32 phy_data)
{
whereami("phy_write_1bit\n");
outl(phy_data, ee_addr); /* MII Clock Low */
eeprom_delay();
outl(phy_data|MDCLKH, ee_addr); /* MII Clock High */
eeprom_delay();
outl(phy_data, ee_addr); /* MII Clock Low */
eeprom_delay();
}
/*
Read one bit phy data from PHY controller
*/
static int phy_read_1bit(u32 ee_addr)
{
int phy_data;
whereami("phy_read_1bit\n");
outl(0x50000, ee_addr);
eeprom_delay();
phy_data=(inl(ee_addr)>>19) & 0x1;
outl(0x40000, ee_addr);
eeprom_delay();
return phy_data;
}
/*
DM9801/DM9802 present check and program
*/
static void HPNA_process(void)
{
if ( (phy_read(3) & 0xfff0) == 0xb900 ) {
if ( phy_read(31) == 0x4404 ) {
/* DM9801 present */
if (phy_read(3) == 0xb901)
phy_write(16, 0x5); /* DM9801 E4 */
else
phy_write(16, 0x1005); /* DM9801 E3 and others */
phy_write(25, ((phy_read(24) + 3) & 0xff) | 0xf000);
} else {
/* DM9802 present */
phy_write(16, 0x5);
phy_write(25, (phy_read(25) & 0xff00) + 2);
}
}
}
/*
Sense media mode and set CR6
*/
static void davicom_media_chk(struct nic * nic)
{
unsigned long to, csr6;
csr6 = 0x00200000; /* SF */
outl(csr6, ioaddr + CSR6);
if (vendor == PCI_VENDOR_ID_DAVICOM && dev_id == PCI_DEVICE_ID_DM9009) {
/* Set to 10BaseT mode for DM9009 */
phy_write(0, 0);
} else {
/* For DM9102/DM9102A */
to = currticks() + 2 * TICKS_PER_SEC;
while ( ((phy_read(1) & 0x24)!=0x24) && (currticks() < to))
/* wait */ ;
if ( (phy_read(1) & 0x24) == 0x24 ) {
if (phy_read(17) & 0xa000)
csr6 |= 0x00000200; /* Full Duplex mode */
} else
csr6 |= 0x00040000; /* Select DM9801/DM9802 when Ethernet link failed */
}
/* set the chip's operating mode */
outl(csr6, ioaddr + CSR6);
/* DM9801/DM9802 present check & program */
if (csr6 & 0x40000)
HPNA_process();
}
/*********************************************************************/
/* 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;
}
/*********************************************************************/
/* davicom_init_chain - setup the tx and rx descriptors */
/* Sten 10/9 */
/*********************************************************************/
static void davicom_init_chain(struct nic *nic)
{
int i;
/* setup the transmit descriptor */
/* Sten: Set 2 TX descriptor but use one TX buffer because
it transmit a packet and wait complete every time. */
for (i=0; i<NTXD; i++) {
txd[i].buf1addr = &txb[0]; /* Used same TX buffer */
txd[i].buf2addr = (unsigned char *)&txd[i+1]; /* Point to Next TX desc */
txd[i].buf1sz = 0;
txd[i].buf2sz = 0;
txd[i].control = 0x184; /* Begin/End/Chain */
txd[i].status = 0x00000000; /* give ownership to Host */
}
/* 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 = (unsigned char *)&rxd[i+1]; /* Point to Next RX desc */
rxd[i].buf1sz = BUFLEN;
rxd[i].buf2sz = 0; /* not used */
rxd[i].control = 0x4; /* Chain Structure */
rxd[i].status = 0x80000000; /* give ownership to device */
}
/* Chain the last descriptor to first */
txd[NTXD - 1].buf2addr = (unsigned char *)&txd[0];
rxd[NRXD - 1].buf2addr = (unsigned char *)&rxd[0];
TxPtr = 0;
rxd_tail = 0;
}
/*********************************************************************/
/* davicom_reset - Reset adapter */
/*********************************************************************/
static void davicom_reset(struct nic *nic)
{
unsigned long to;
u32 addr_low, addr_high;
whereami("davicom_reset\n");
/* Stop Tx and RX */
outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
outl(0x00000001, ioaddr + CSR0);
davicom_wait(TICKS_PER_SEC);
/* TX/RX descriptor burst */
outl(0x0C00000, ioaddr + CSR0); /* Sten 10/9 */
/* set up transmit and receive descriptors */
davicom_init_chain(nic); /* Sten 10/9 */
/* Point to receive descriptor */
outl((unsigned long)&rxd[0], ioaddr + CSR3);
outl((unsigned long)&txd[0], ioaddr + CSR4); /* Sten 10/9 */
/* According phyxcer media mode to set CR6,
DM9102/A phyxcer can auto-detect media mode */
davicom_media_chk(nic);
/* Prepare Setup Frame Sten 10/9 */
txd[TxPtr].buf1sz = 192;
txd[TxPtr].control = 0x024; /* SF/CE */
txd[TxPtr].status = 0x80000000; /* Give ownership to device */
/* Start Tx */
outl(inl(ioaddr + CSR6) | 0x00002000, ioaddr + CSR6);
/* immediate transmit demand */
outl(0, ioaddr + CSR1);
to = currticks() + TX_TIME_OUT;
while ((txd[TxPtr].status & 0x80000000) && (currticks() < to)) /* Sten 10/9 */
/* wait */ ;
if (currticks() >= to) {
printf ("TX Setup Timeout!\n");
}
/* Point to next TX descriptor */
TxPtr = (++TxPtr >= NTXD) ? 0:TxPtr; /* Sten 10/9 */
#ifdef DAVICOM_DEBUG
printf("txd.status = %X\n", txd.status);
printf("ticks = %d\n", currticks() - (to - TX_TIME_OUT));
davicom_more();
#endif
/* enable RX */
outl(inl(ioaddr + CSR6) | 0x00000002, ioaddr + CSR6);
/* immediate poll demand */
outl(0, ioaddr + CSR2);
}
/*********************************************************************/
/* eth_transmit - Transmit a frame */
/*********************************************************************/
static void davicom_transmit(struct nic *nic, const char *d, unsigned int t,
unsigned int s, const char *p)
{
unsigned long to;
whereami("davicom_transmit\n");
/* Stop Tx */
/* outl(inl(ioaddr + CSR6) & ~0x00002000, ioaddr + CSR6); */
/* setup ethernet header */
memcpy(&txb[0], d, ETH_ALEN); /* DA 6byte */
memcpy(&txb[ETH_ALEN], nic->node_addr, ETH_ALEN); /* SA 6byte*/
txb[ETH_ALEN*2] = (t >> 8) & 0xFF; /* Frame type: 2byte */
txb[ETH_ALEN*2+1] = t & 0xFF;
memcpy(&txb[ETH_HLEN], p, s); /* Frame data */
/* setup the transmit descriptor */
txd[TxPtr].buf1sz = ETH_HLEN+s;
txd[TxPtr].control = 0x00000184; /* LS+FS+CE */
txd[TxPtr].status = 0x80000000; /* give ownership to device */
/* immediate transmit demand */
outl(0, ioaddr + CSR1);
to = currticks() + TX_TIME_OUT;
while ((txd[TxPtr].status & 0x80000000) && (currticks() < to))
/* wait */ ;
if (currticks() >= to) {
printf ("TX Timeout!\n");
}
/* Point to next TX descriptor */
TxPtr = (++TxPtr >= NTXD) ? 0:TxPtr; /* Sten 10/9 */
}
/*********************************************************************/
/* eth_poll - Wait for a frame */
/*********************************************************************/
static int davicom_poll(struct nic *nic)
{
whereami("davicom_poll\n");
if (rxd[rxd_tail].status & 0x80000000)
return 0;
whereami("davicom_poll got one\n");
nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16;
if( rxd[rxd_tail].status & 0x00008000){
rxd[rxd_tail].status = 0x80000000;
rxd_tail++;
if (rxd_tail == NRXD) rxd_tail = 0;
return 0;
}
/* 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 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 davicom_disable(struct nic *nic)
{
whereami("davicom_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 *davicom_probe(struct nic *nic, unsigned short *io_addrs,
struct pci_device *pci)
{
unsigned int i;
u32 l1, l2;
whereami("davicom_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(pci->bus, 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 */
/* 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<ETH_ALEN; i++)
nic->node_addr[i] = ee_data[20+i];
printf("Davicom %! at ioaddr %#hX\n", nic->node_addr, ioaddr);
/* initialize device */
davicom_reset(nic);
nic->reset = davicom_reset;
nic->poll = davicom_poll;
nic->transmit = davicom_transmit;
nic->disable = davicom_disable;
return nic;
}

View file

@ -351,59 +351,6 @@
#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
*/
@ -416,14 +363,11 @@ static int depca_debug = 1;
**
** 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 NUM_RX_DESC 2 /* Number of RX descriptors */
#define NUM_TX_DESC 2 /* 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 */
/*
** ISA Bus defines
*/
@ -494,25 +438,31 @@ struct depca_tx_desc {
*/
struct depca_init {
u16 mode; /* Mode register */
u8 phys_addr[ETHER_ADDR_SIZE]; /* Physical ethernet address */
u8 phys_addr[ETH_ALEN]; /* 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 */
};
/*
** 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)
struct depca_private {
struct depca_rx_desc *rx_ring;
struct depca_tx_desc *tx_ring;
struct depca_init init_block; /* Shadow init block */
char *rx_memcpy[NUM_RX_DESC];
char *tx_memcpy[NUM_TX_DESC];
u32 bus_offset; /* ISA bus address offset */
u32 sh_mem; /* address of shared mem */
u32 dma_buffs; /* Rx & Tx buffer start */
int rx_cur, tx_cur; /* Next free ring entry */
int txRingMask, rxRingMask;
s32 rx_rlen, tx_rlen;
/* log2([rt]xRingMask+1) for the descriptors */
};
static Address mem_start = DEPCA_RAM_BASE;
static Address mem_len, offset;
static unsigned short ioaddr = 0;
static struct depca_private lp;
/*
** Miscellaneous defines...
@ -521,7 +471,64 @@ static unsigned short ioaddr = 0;
outw(CSR0, DEPCA_ADDR);\
outw(STOP, DEPCA_DATA)
/* Initialize the lance Rx and Tx descriptor rings. */
static void depca_init_ring(struct nic *nic)
{
int i;
u32 p;
lp.rx_cur = lp.tx_cur = 0;
/* Initialize the base addresses and length of each buffer in the ring */
for (i = 0; i <= lp.rxRingMask; i++) {
writel((p = lp.dma_buffs + i * RX_BUFF_SZ) | R_OWN, &lp.rx_ring[i].base);
writew(-RX_BUFF_SZ, &lp.rx_ring[i].buf_length);
lp.rx_memcpy[i] = (char *) (p + lp.bus_offset);
}
for (i = 0; i <= lp.txRingMask; i++) {
writel((p = lp.dma_buffs + (i + lp.txRingMask + 1) * TX_BUFF_SZ) & 0x00ffffff, &lp.tx_ring[i].base);
lp.tx_memcpy[i] = (char *) (p + lp.bus_offset);
}
/* Set up the initialization block */
lp.init_block.rx_ring = ((u32) ((u32) lp.rx_ring) & LA_MASK) | lp.rx_rlen;
lp.init_block.tx_ring = ((u32) ((u32) lp.tx_ring) & LA_MASK) | lp.tx_rlen;
for (i = 0; i < ETH_ALEN; i++)
lp.init_block.phys_addr[i] = nic->node_addr[i];
lp.init_block.mode = 0x0000; /* Enable the Tx and Rx */
memset(lp.init_block.mcast_table, 0, sizeof(lp.init_block.mcast_table));
}
static void LoadCSRs(void)
{
outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */
outw((u16) (lp.sh_mem & LA_MASK), DEPCA_DATA);
outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */
outw((u16) ((lp.sh_mem & LA_MASK) >> 16), DEPCA_DATA);
outw(CSR3, DEPCA_ADDR); /* ALE control */
outw(ACON, DEPCA_DATA);
outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */
}
static int InitRestartDepca(void)
{
int i;
/* Copy the shadow init_block to shared memory */
memcpy_toio((char *)lp.sh_mem, &lp.init_block, sizeof(struct depca_init));
outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */
outw(INIT, DEPCA_DATA); /* initialise DEPCA */
for (i = 0; i < 100 && !(inw(DEPCA_DATA) & IDON); i++)
;
if (i < 100) {
/* clear IDON by writing a 1, and start LANCE */
outw(IDON | STRT, DEPCA_DATA);
} else {
printf("DEPCA not initialised\n");
return (1);
}
return (0);
}
/**************************************************************************
RESET - Reset adapter
@ -529,15 +536,50 @@ RESET - Reset adapter
static void depca_reset(struct nic *nic)
{
s16 nicsr;
int status = 0;
int i, j;
STOP_DEPCA;
nicsr = inb(DEPCA_NICSR);
nicsr = ((nicsr & ~SHE & ~RBE & ~IEN) | IM);
outb(nicsr, DEPCA_NICSR);
if (inw(DEPCA_DATA) != STOP)
{
printf("depca: Cannot stop NIC\n");
return;
}
/* non-DEPCA need this */
if (adapter != DEPCA)
outb(nicsr | SHE, DEPCA_NICSR);
/* Initialisation block */
lp.sh_mem = mem_start;
mem_start += sizeof(struct depca_init);
/* Tx & Rx descriptors (aligned to a quadword boundary) */
mem_start = (mem_start + ALIGN) & ~ALIGN;
lp.rx_ring = (struct depca_rx_desc *) mem_start;
mem_start += (sizeof(struct depca_rx_desc) * NUM_RX_DESC);
lp.tx_ring = (struct depca_tx_desc *) mem_start;
mem_start += (sizeof(struct depca_tx_desc) * NUM_TX_DESC);
lp.bus_offset = mem_start & 0x00ff0000;
/* LANCE re-mapped start address */
lp.dma_buffs = mem_start & LA_MASK;
/* Finish initialising the ring information. */
lp.rxRingMask = NUM_RX_DESC - 1;
lp.txRingMask = NUM_TX_DESC - 1;
/* Calculate Tx/Rx RLEN size for the descriptors. */
for (i = 0, j = lp.rxRingMask; j > 0; i++) {
j >>= 1;
}
lp.rx_rlen = (s32) (i << 29);
for (i = 0, j = lp.txRingMask; j > 0; i++) {
j >>= 1;
}
lp.tx_rlen = (s32) (i << 29);
/* Load the initialisation block */
depca_init_ring(nic);
LoadCSRs();
InitRestartDepca();
}
/**************************************************************************
@ -545,10 +587,16 @@ 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;
int entry;
u32 status;
entry = lp.rx_cur;
if ((status = readl(&lp.rx_ring[entry].base) & R_OWN))
return (0);
memcpy(nic->packet, lp.rx_memcpy[entry], nic->packetlen = lp.rx_ring[entry].msg_length);
lp.rx_ring[entry].base |= R_OWN;
lp.rx_cur = (++lp.rx_cur) & lp.rxRingMask;
return (1);
}
/**************************************************************************
@ -561,7 +609,33 @@ static void depca_transmit(
unsigned int s, /* size */
const char *p) /* Packet */
{
int entry, len;
char *mem;
/* send the packet to destination */
/*
** Caution: the right order is important here... dont
** setup the ownership rights until all the other
** information is in place
*/
mem = lp.tx_memcpy[entry = lp.tx_cur];
memcpy_toio(mem, d, ETH_ALEN);
memcpy_toio(mem + ETH_ALEN, nic->node_addr, ETH_ALEN);
mem[ETH_ALEN * 2] = t >> 8;
mem[ETH_ALEN * 2 + 1] = t;
memcpy_toio(mem + ETH_HLEN, p, s);
s += ETH_HLEN;
len = (s < ETH_ZLEN ? ETH_ZLEN : s);
/* clean out flags */
writel(readl(&lp.tx_ring[entry].base) & ~T_FLAGS, &lp.tx_ring[entry].base);
/* clears other error flags */
writew(0x0000, &lp.tx_ring[entry].misc);
/* packet length in buffer */
writew(-len, &lp.tx_ring[entry].length);
/* start and end of packet, ownership */
writel(readl(&lp.tx_ring[entry].base) | (T_STP|T_ENP|T_OWN), &lp.tx_ring[entry].base);
/* update current pointers */
lp.tx_cur = (++lp.tx_cur) & lp.txRingMask;
}
/**************************************************************************
@ -569,6 +643,7 @@ DISABLE - Turn off ethernet interface
***************************************************************************/
static void depca_disable(struct nic *nic)
{
STOP_DEPCA;
}
/*
@ -594,7 +669,6 @@ static int depca_probe1(struct nic *nic)
u8 sig[] = { 0xFF, 0x00, 0x55, 0xAA, 0xFF, 0x00, 0x55, 0xAA };
int i, j;
long sum, chksum;
Address mem_len, offset;
data = inb(DEPCA_PROM); /* clear counter on DEPCA */
data = inb(DEPCA_PROM); /* read data */
@ -641,18 +715,14 @@ static int depca_probe1(struct nic *nic)
nicsr &= ~BS;
mem_len -= (32 << 10);
}
if (adapter != DEPCA)
if (adapter != DEPCA) /* enable shadow RAM */
outb(nicsr |= SHE, DEPCA_NICSR);
printf("%s base 0x%x, memory [0x%X-0x%X], addr ", adapter_name[adapter],
ioaddr, mem_start, mem_start + mem_len);
for (i = 0; i < ETHER_ADDR_SIZE; i++) {
if (i != 0)
putchar(':');
printf("%b", nic->node_addr[i]);
}
printf("%s base %#hX, memory [%#hX-%#hX], addr %!",
adapter_name[adapter], ioaddr, mem_start, mem_start + mem_len,
nic->node_addr);
if (sum != chksum)
printf(" (bad checksum)");
printf("\n");
putchar('\n');
return (1);
}
@ -664,21 +734,19 @@ struct nic *depca_probe(struct nic *nic, unsigned short *probe_addrs)
static unsigned short base[] = DEPCA_IO_PORTS;
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 (depca_probe1(nic))
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;
if (ioaddr == 0)
return (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);
}

586
netboot/eepro.c Normal file
View file

@ -0,0 +1,586 @@
/**************************************************************************
Etherboot - BOOTP/TFTP Bootstrap Program
Intel EEPRO/10 NIC driver for Etherboot
Adapted from Linux eepro.c from kernel 2.2.17
This board accepts a 32 pin EEPROM (29C256), however a test with a
27C010 shows that this EPROM also works in the socket, but it's not clear
how repeatably. The two top address pins appear to be held low, thus
the bottom 32kB of the 27C010 is visible in the CPU's address space.
To be sure you could put 4 copies of the code in the 27C010, then
it doesn't matter whether the extra lines are held low or high, just
hopefully not floating as CMOS chips don't like floating inputs.
Be careful with seating the EPROM as the socket on my board actually
has 34 pins, the top row of 2 are not used.
***************************************************************************/
/*
* This program is free software; you can redistribute 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.
*/
/* to get some global routines like printf */
#include "etherboot.h"
/* to get the interface to the body of the program */
#include "nic.h"
/* to get our own prototype */
#include "cards.h"
/* we use timer2 for microsecond waits */
#include "timer.h"
#undef DEBUG /* only after include files */
/* Different 82595 chips */
#define LAN595 0
#define LAN595TX 1
#define LAN595FX 2
#define LAN595FX_10ISA 3
#define SLOW_DOWN inb(0x80);
/* The station (ethernet) address prefix, used for IDing the board. */
#define SA_ADDR0 0x00 /* Etherexpress Pro/10 */
#define SA_ADDR1 0xaa
#define SA_ADDR2 0x00
#define GetBit(x,y) ((x & (1<<y))>>y)
/* EEPROM Word 0: */
#define ee_PnP 0 /* Plug 'n Play enable bit */
#define ee_Word1 1 /* Word 1? */
#define ee_BusWidth 2 /* 8/16 bit */
#define ee_FlashAddr 3 /* Flash Address */
#define ee_FlashMask 0x7 /* Mask */
#define ee_AutoIO 6 /* */
#define ee_reserved0 7 /* =0! */
#define ee_Flash 8 /* Flash there? */
#define ee_AutoNeg 9 /* Auto Negotiation enabled? */
#define ee_IO0 10 /* IO Address LSB */
#define ee_IO0Mask 0x /*...*/
#define ee_IO1 15 /* IO MSB */
/* EEPROM Word 1: */
#define ee_IntSel 0 /* Interrupt */
#define ee_IntMask 0x7
#define ee_LI 3 /* Link Integrity 0= enabled */
#define ee_PC 4 /* Polarity Correction 0= enabled */
#define ee_TPE_AUI 5 /* PortSelection 1=TPE */
#define ee_Jabber 6 /* Jabber prevention 0= enabled */
#define ee_AutoPort 7 /* Auto Port Selection 1= Disabled */
#define ee_SMOUT 8 /* SMout Pin Control 0= Input */
#define ee_PROM 9 /* Flash EPROM / PROM 0=Flash */
#define ee_reserved1 10 /* .. 12 =0! */
#define ee_AltReady 13 /* Alternate Ready, 0=normal */
#define ee_reserved2 14 /* =0! */
#define ee_Duplex 15
/* Word2,3,4: */
#define ee_IA5 0 /*bit start for individual Addr Byte 5 */
#define ee_IA4 8 /*bit start for individual Addr Byte 5 */
#define ee_IA3 0 /*bit start for individual Addr Byte 5 */
#define ee_IA2 8 /*bit start for individual Addr Byte 5 */
#define ee_IA1 0 /*bit start for individual Addr Byte 5 */
#define ee_IA0 8 /*bit start for individual Addr Byte 5 */
/* Word 5: */
#define ee_BNC_TPE 0 /* 0=TPE */
#define ee_BootType 1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */
#define ee_BootTypeMask 0x3
#define ee_NumConn 3 /* Number of Connections 0= One or Two */
#define ee_FlashSock 4 /* Presence of Flash Socket 0= Present */
#define ee_PortTPE 5
#define ee_PortBNC 6
#define ee_PortAUI 7
#define ee_PowerMgt 10 /* 0= disabled */
#define ee_CP 13 /* Concurrent Processing */
#define ee_CPMask 0x7
/* Word 6: */
#define ee_Stepping 0 /* Stepping info */
#define ee_StepMask 0x0F
#define ee_BoardID 4 /* Manucaturer Board ID, reserved */
#define ee_BoardMask 0x0FFF
/* Word 7: */
#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping = 0x1EB8 for Pro/10+ */
#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */
/*..*/
#define ee_SIZE 0x40 /* total EEprom Size */
#define ee_Checksum 0xBABA /* initial and final value for adding checksum */
/* Card identification via EEprom: */
#define ee_addr_vendor 0x10 /* Word offset for EISA Vendor ID */
#define ee_addr_id 0x11 /* Word offset for Card ID */
#define ee_addr_SN 0x12 /* Serial Number */
#define ee_addr_CRC_8 0x14 /* CRC over last thee Bytes */
#define ee_vendor_intel0 0x25 /* Vendor ID Intel */
#define ee_vendor_intel1 0xD4
#define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */
#define ee_id_eepro10p1 0x31
/* now this section could be used by both boards: the oldies and the ee10:
* ee10 uses tx buffer before of rx buffer and the oldies the inverse.
* (aris)
*/
#define RAM_SIZE 0x8000
#define RCV_HEADER 8
#define RCV_DEFAULT_RAM 0x6000
#define RCV_RAM rcv_ram
static unsigned rcv_ram = RCV_DEFAULT_RAM;
#define XMT_HEADER 8
#define XMT_RAM (RAM_SIZE - RCV_RAM)
#define XMT_START ((rcv_start + RCV_RAM) % RAM_SIZE)
#define RCV_LOWER_LIMIT (rcv_start >> 8)
#define RCV_UPPER_LIMIT (((rcv_start + RCV_RAM) - 2) >> 8)
#define XMT_LOWER_LIMIT (XMT_START >> 8)
#define XMT_UPPER_LIMIT (((XMT_START + XMT_RAM) - 2) >> 8)
#define RCV_START_PRO 0x00
#define RCV_START_10 XMT_RAM
/* by default the old driver */
static unsigned rcv_start = RCV_START_PRO;
#define RCV_DONE 0x0008
#define RX_OK 0x2000
#define RX_ERROR 0x0d81
#define TX_DONE_BIT 0x0080
#define CHAIN_BIT 0x8000
#define XMT_STATUS 0x02
#define XMT_CHAIN 0x04
#define XMT_COUNT 0x06
#define BANK0_SELECT 0x00
#define BANK1_SELECT 0x40
#define BANK2_SELECT 0x80
/* Bank 0 registers */
#define COMMAND_REG 0x00 /* Register 0 */
#define MC_SETUP 0x03
#define XMT_CMD 0x04
#define DIAGNOSE_CMD 0x07
#define RCV_ENABLE_CMD 0x08
#define RCV_DISABLE_CMD 0x0a
#define STOP_RCV_CMD 0x0b
#define RESET_CMD 0x0e
#define POWER_DOWN_CMD 0x18
#define RESUME_XMT_CMD 0x1c
#define SEL_RESET_CMD 0x1e
#define STATUS_REG 0x01 /* Register 1 */
#define RX_INT 0x02
#define TX_INT 0x04
#define EXEC_STATUS 0x30
#define ID_REG 0x02 /* Register 2 */
#define R_ROBIN_BITS 0xc0 /* round robin counter */
#define ID_REG_MASK 0x2c
#define ID_REG_SIG 0x24
#define AUTO_ENABLE 0x10
#define INT_MASK_REG 0x03 /* Register 3 */
#define RX_STOP_MASK 0x01
#define RX_MASK 0x02
#define TX_MASK 0x04
#define EXEC_MASK 0x08
#define ALL_MASK 0x0f
#define IO_32_BIT 0x10
#define RCV_BAR 0x04 /* The following are word (16-bit) registers */
#define RCV_STOP 0x06
#define XMT_BAR_PRO 0x0a
#define XMT_BAR_10 0x0b
static unsigned xmt_bar = XMT_BAR_PRO;
#define HOST_ADDRESS_REG 0x0c
#define IO_PORT 0x0e
#define IO_PORT_32_BIT 0x0c
/* Bank 1 registers */
#define REG1 0x01
#define WORD_WIDTH 0x02
#define INT_ENABLE 0x80
#define INT_NO_REG 0x02
#define RCV_LOWER_LIMIT_REG 0x08
#define RCV_UPPER_LIMIT_REG 0x09
#define XMT_LOWER_LIMIT_REG_PRO 0x0a
#define XMT_UPPER_LIMIT_REG_PRO 0x0b
#define XMT_LOWER_LIMIT_REG_10 0x0b
#define XMT_UPPER_LIMIT_REG_10 0x0a
static unsigned xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
static unsigned xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
/* Bank 2 registers */
#define XMT_Chain_Int 0x20 /* Interrupt at the end of the transmit chain */
#define XMT_Chain_ErrStop 0x40 /* Interrupt at the end of the chain even if there are errors */
#define RCV_Discard_BadFrame 0x80 /* Throw bad frames away, and continue to receive others */
#define REG2 0x02
#define PRMSC_Mode 0x01
#define Multi_IA 0x20
#define REG3 0x03
#define TPE_BIT 0x04
#define BNC_BIT 0x20
#define REG13 0x0d
#define FDX 0x00
#define A_N_ENABLE 0x02
#define I_ADD_REG0 0x04
#define I_ADD_REG1 0x05
#define I_ADD_REG2 0x06
#define I_ADD_REG3 0x07
#define I_ADD_REG4 0x08
#define I_ADD_REG5 0x09
#define EEPROM_REG_PRO 0x0a
#define EEPROM_REG_10 0x0b
static unsigned eeprom_reg = EEPROM_REG_PRO;
#define EESK 0x01
#define EECS 0x02
#define EEDI 0x04
#define EEDO 0x08
/* The horrible routine to read a word from the serial EEPROM. */
/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
/* The delay between EEPROM clock transitions. */
#define eeprom_delay() { udelay(40); }
#define EE_READ_CMD (6 << 6)
/* do a full reset */
#define eepro_full_reset(ioaddr) outb(RESET_CMD, ioaddr); udelay(40);
/* do a nice reset */
#define eepro_sel_reset(ioaddr) { \
outb(SEL_RESET_CMD, ioaddr); \
SLOW_DOWN; \
SLOW_DOWN; \
}
/* clear all interrupts */
#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG)
/* enable rx */
#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr)
/* disable rx */
#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr)
/* switch bank */
#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr)
#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr)
#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr)
static unsigned int rx_start, tx_start;
static int tx_last;
static unsigned tx_end;
static int eepro = 0;
static unsigned short ioaddr = 0;
static unsigned int mem_start, mem_end = RCV_DEFAULT_RAM / 1024;
#define udelay(n) waiton_timer2(((n)*TICKS_PER_MS)/1000)
/**************************************************************************
RESET - Reset adapter
***************************************************************************/
static void eepro_reset(struct nic *nic)
{
int temp_reg, i;
/* put the card in its initial state */
eepro_sw2bank2(ioaddr); /* be careful, bank2 now */
temp_reg = inb(ioaddr + eeprom_reg);
#ifdef DEBUG
printf("Stepping %d\n", temp_reg >> 5);
#endif
if (temp_reg & 0x10) /* check the TurnOff Enable bit */
outb(temp_reg & 0xEF, ioaddr + eeprom_reg);
for (i = 0; i < ETH_ALEN; i++) /* fill the MAC address */
outb(nic->node_addr[i], ioaddr + I_ADD_REG0 + i);
temp_reg = inb(ioaddr + REG1);
/* setup Transmit Chaining and discard bad RCV frames */
outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop
| RCV_Discard_BadFrame, ioaddr + REG1);
temp_reg = inb(ioaddr + REG2); /* match broadcast */
outb(temp_reg | 0x14, ioaddr + REG2);
temp_reg = inb(ioaddr + REG3);
outb(temp_reg & 0x3F, ioaddr + REG3); /* clear test mode */
/* set the receiving mode */
eepro_sw2bank1(ioaddr); /* be careful, bank1 now */
/* initialise the RCV and XMT upper and lower limits */
outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG);
outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG);
outb(XMT_LOWER_LIMIT, ioaddr + xmt_lower_limit_reg);
outb(XMT_UPPER_LIMIT, ioaddr + xmt_upper_limit_reg);
eepro_sw2bank0(ioaddr); /* Switch back to bank 0 */
eepro_clear_int(ioaddr);
/* Initialise RCV */
outw(rx_start = (RCV_LOWER_LIMIT << 8), ioaddr + RCV_BAR);
outw(((RCV_UPPER_LIMIT << 8) | 0xFE), ioaddr + RCV_STOP);
/* Intialise XMT */
outw((XMT_LOWER_LIMIT << 8), ioaddr + xmt_bar);
eepro_sel_reset(ioaddr);
tx_start = tx_end = (XMT_LOWER_LIMIT << 8);
tx_last = 0;
eepro_en_rx(ioaddr);
}
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
static int eepro_poll(struct nic *nic)
{
int i;
unsigned int rcv_car = rx_start;
unsigned int rcv_event, rcv_status, rcv_next_frame, rcv_size;
/* 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 */
#if 0
if ((inb(ioaddr + STATUS_REG) & 0x40) == 0)
return (0);
outb(0x40, ioaddr + STATUS_REG);
#endif
outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
rcv_event = inw(ioaddr + IO_PORT);
if (rcv_event != RCV_DONE)
return (0);
rcv_status = inw(ioaddr + IO_PORT);
rcv_next_frame = inw(ioaddr + IO_PORT);
rcv_size = inw(ioaddr + IO_PORT);
#if 0
printf("%hX %hX %d %hhX\n", rcv_status, rcv_next_frame, rcv_size,
inb(ioaddr + STATUS_REG));
#endif
if ((rcv_status & (RX_OK|RX_ERROR)) != RX_OK) {
printf("Receive error %hX\n", rcv_status);
return (0);
}
rcv_size &= 0x3FFF;
insw(ioaddr + IO_PORT, nic->packet, ((rcv_size + 3) >> 1));
#if 0
for (i = 0; i < 48; i++) {
printf("%hhX", nic->packet[i]);
putchar(i % 16 == 15 ? '\n' : ' ');
}
#endif
nic->packetlen = rcv_size;
rcv_car = rx_start + RCV_HEADER + rcv_size;
rx_start = rcv_next_frame;
if (rcv_car == 0)
rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff);
outw(rcv_car - 1, ioaddr + RCV_STOP);
return (1);
}
/**************************************************************************
TRANSMIT - Transmit a frame
***************************************************************************/
static void eepro_transmit(
struct nic *nic,
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
const char *p) /* Packet */
{
unsigned int status, tx_available, last, end, length;
unsigned short type;
int boguscount = 20;
length = s + ETH_HLEN;
if (tx_end > tx_start)
tx_available = XMT_RAM - (tx_end - tx_start);
else if (tx_end < tx_start)
tx_available = tx_start - tx_end;
else
tx_available = XMT_RAM;
last = tx_end;
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
if (end >= (XMT_UPPER_LIMIT << 8)) {
last = (XMT_LOWER_LIMIT << 8);
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
}
outw(last, ioaddr + HOST_ADDRESS_REG);
outw(XMT_CMD, ioaddr + IO_PORT);
outw(0, ioaddr + IO_PORT);
outw(end, ioaddr + IO_PORT);
outw(length, ioaddr + IO_PORT);
outsw(ioaddr + IO_PORT, d, ETH_ALEN / 2);
outsw(ioaddr + IO_PORT, nic->node_addr, ETH_ALEN / 2);
type = htons(t);
outsw(ioaddr + IO_PORT, &type, sizeof(type) / 2);
outsw(ioaddr + IO_PORT, p, (s + 3) >> 1);
/* A dummy read to flush the DRAM write pipeline */
status = inw(ioaddr + IO_PORT);
outw(last, ioaddr + xmt_bar);
outb(XMT_CMD, ioaddr);
tx_start = last;
tx_last = last;
tx_end = end;
#if 0
printf("%d %d\n", tx_start, tx_end);
#endif
while (boguscount > 0) {
if (((status = inw(ioaddr + IO_PORT)) & TX_DONE_BIT) == 0) {
udelay(40);
boguscount--;
continue;
}
#if DEBUG
if ((status & 0x2000) == 0)
printf("Transmit status %hX\n", status);
#endif
}
}
/**************************************************************************
DISABLE - Turn off ethernet interface
***************************************************************************/
static void eepro_disable(struct nic *nic)
{
eepro_sw2bank0(ioaddr); /* Switch to bank 0 */
/* Flush the Tx and disable Rx */
outb(STOP_RCV_CMD, ioaddr);
tx_start = tx_end = (XMT_LOWER_LIMIT << 8);
tx_last = 0;
/* Reset the 82595 */
eepro_full_reset(ioaddr);
}
static int read_eeprom(int location)
{
int i;
unsigned short retval = 0;
int ee_addr = ioaddr + eeprom_reg;
int read_cmd = location | EE_READ_CMD;
int ctrl_val = EECS;
if (eepro == LAN595FX_10ISA) {
eepro_sw2bank1(ioaddr);
outb(0x00, ioaddr + STATUS_REG);
}
eepro_sw2bank2(ioaddr);
outb(ctrl_val, ee_addr);
/* shift the read command bits out */
for (i = 8; i >= 0; i--) {
short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val;
outb(outval, ee_addr);
outb(outval | EESK, ee_addr); /* EEPROM clock tick */
eeprom_delay();
outb(outval, ee_addr); /* finish EEPROM clock tick */
eeprom_delay();
}
outb(ctrl_val, ee_addr);
for (i = 16; i > 0; i--) {
outb(ctrl_val | EESK, ee_addr);
eeprom_delay();
retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
outb(ctrl_val, ee_addr);
eeprom_delay();
}
/* terminate the EEPROM access */
ctrl_val &= ~EECS;
outb(ctrl_val | EESK, ee_addr);
eeprom_delay();
outb(ctrl_val, ee_addr);
eeprom_delay();
eepro_sw2bank0(ioaddr);
return (retval);
}
static int eepro_probe1(struct nic *nic)
{
int i, id, counter, l_eepro = 0;
union {
unsigned char caddr[ETH_ALEN];
unsigned short saddr[ETH_ALEN/2];
} station_addr;
char *name;
id = inb(ioaddr + ID_REG);
if ((id & ID_REG_MASK) != ID_REG_SIG)
return (0);
counter = id & R_ROBIN_BITS;
if (((id = inb(ioaddr + ID_REG)) & R_ROBIN_BITS) != (counter + 0x40))
return (0);
/* yes the 82595 has been found */
station_addr.saddr[2] = read_eeprom(2);
if (station_addr.saddr[2] == 0x0000 || station_addr.saddr[2] == 0xFFFF) {
l_eepro = 3;
eepro = LAN595FX_10ISA;
eeprom_reg= EEPROM_REG_10;
rcv_start = RCV_START_10;
xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
station_addr.saddr[2] = read_eeprom(2);
}
station_addr.saddr[1] = read_eeprom(3);
station_addr.saddr[0] = read_eeprom(4);
if (l_eepro)
name = "Intel EtherExpress 10 ISA";
else if (read_eeprom(7) == ee_FX_INT2IRQ) {
name = "Intel EtherExpress Pro/10+ ISA";
l_eepro = 2;
} else if (station_addr.saddr[0] == SA_ADDR1) {
name = "Intel EtherExpress Pro/10 ISA";
l_eepro = 1;
} else {
l_eepro = 0;
name = "Intel 82595-based LAN card";
}
station_addr.saddr[0] = swap16(station_addr.saddr[0]);
station_addr.saddr[1] = swap16(station_addr.saddr[1]);
station_addr.saddr[2] = swap16(station_addr.saddr[2]);
for (i = 0; i < ETH_ALEN; i++) {
nic->node_addr[i] = station_addr.caddr[i];
}
printf("\n%s ioaddr %#hX, addr %!", name, ioaddr, nic->node_addr);
mem_start = RCV_LOWER_LIMIT << 8;
if ((mem_end & 0x3F) < 3 || (mem_end & 0x3F) > 29)
mem_end = RCV_UPPER_LIMIT << 8;
else {
mem_end = mem_end * 1024 + (RCV_LOWER_LIMIT << 8);
rcv_ram = mem_end - (RCV_LOWER_LIMIT << 8);
}
printf(", Rx mem %dK, if %s\n", (mem_end - mem_start) >> 10,
GetBit(read_eeprom(5), ee_BNC_TPE) ? "BNC" : "TP");
return (1);
}
/**************************************************************************
PROBE - Look for an adapter, this routine's visible to the outside
***************************************************************************/
struct nic *eepro_probe(struct nic *nic, unsigned short *probe_addrs)
{
unsigned short *p;
/* same probe list as the Linux driver */
static unsigned short ioaddrs[] = {
0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
if (probe_addrs == 0 || probe_addrs[0] == 0)
probe_addrs = ioaddrs;
for (p = probe_addrs; (ioaddr = *p) != 0; p++) {
if (eepro_probe1(nic))
break;
}
if (*p == 0)
return (0);
eepro_reset(nic);
/* point to NIC specific routines */
nic->reset = eepro_reset;
nic->poll = eepro_poll;
nic->transmit = eepro_transmit;
nic->disable = eepro_disable;
return (nic);
}

View file

@ -46,8 +46,6 @@
* I still don't have the docs.
* */
/* Philosophy of this driver.
*
* Probing:
@ -91,7 +89,6 @@
* so that you need even more headroom.
*/
/* The etherboot authors seem to dislike the argument ordering in
* outb macros that Linux uses. I disklike the confusion that this
* has caused even more.... This file uses the Linux argument ordering. */
@ -101,6 +98,7 @@
#include "nic.h"
#include "pci.h"
#include "cards.h"
#include "timer.h"
#undef virt_to_bus
#define virt_to_bus(x) ((unsigned long)x)
@ -114,7 +112,6 @@ typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
enum speedo_offsets {
SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */
SCBPointer = 4, /* General purpose pointer. */
@ -124,11 +121,8 @@ enum speedo_offsets {
SCBEarlyRx = 20, /* Early receive byte count. */
};
static int read_eeprom(int location);
static void udelay (int val);
void hd (void *where, int n);
static int do_eeprom_cmd(int cmd, int cmd_len);
void hd(void *where, int n);
/***********************************************************************/
/* I82557 related defines */
@ -140,22 +134,15 @@ void hd (void *where, int n);
#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
#define EE_CS 0x02 /* EEPROM chip select. */
#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
#define EE_WRITE_0 0x01
#define EE_WRITE_1 0x05
#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
#define EE_WRITE_0 0x4802
#define EE_WRITE_1 0x4806
#define EE_ENB (0x4800 | EE_CS)
/* Delay between EEPROM clock transitions.
This is a "nasty" timing loop, but PC compatible machines are defined
to delay an ISA compatible period for the SLOW_DOWN_IO macro. */
#define eeprom_delay(nanosec) do { int _i = 3; while (--_i > 0) \
{ __SLOW_DOWN_IO; }} while (0)
#define udelay(n) waiton_timer2(((n)*TICKS_PER_MS)/1000)
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5 << 6)
#define EE_READ_CMD (6 << 6)
#define EE_ERASE_CMD (7 << 6)
#define EE_READ_CMD 6
/* The SCB accepts the following controls for the Tx and Rx units: */
#define CU_START 0x0010
@ -176,8 +163,6 @@ void hd (void *where, int n);
enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
S80C24, PhyUndefined, DP83840A=10, };
/* Commands that can be put in a command list entry. */
enum commands {
CmdNOp = 0,
@ -195,7 +180,6 @@ enum commands {
CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */
};
/* How to wait for the command unit to accept a command.
Typically this takes 0 ticks. */
static inline void wait_for_cmd_done(int cmd_ioaddr)
@ -205,7 +189,6 @@ static inline void wait_for_cmd_done(int cmd_ioaddr)
while(inb(cmd_ioaddr) && --wait >= 0);
}
/* Elements of the dump_statistics block. This block must be lword aligned. */
static struct speedo_stats {
u32 tx_good_frames;
@ -227,7 +210,6 @@ static struct speedo_stats {
u32 done_marker;
} lstats;
/* A speedo3 TX buffer descriptor with two buffers... */
static struct TxFD {
volatile s16 status;
@ -242,7 +224,6 @@ static struct TxFD {
s32 tx_buf_size1; /* Length of Tx data. */
} txfd;
struct RxFD { /* Receive frame descriptor. */
volatile s16 status;
s16 command;
@ -253,7 +234,7 @@ struct RxFD { /* Receive frame descriptor. */
char packet[1518];
};
#ifndef USE_INTERNAL_BUFFER
#ifdef USE_LOWMEM_BUFFER
#define rxfd ((struct RxFD *)(0x10000 - sizeof(struct RxFD)))
#define ACCESS(x) x->
#else
@ -261,16 +242,12 @@ static struct RxFD rxfd;
#define ACCESS(x) x.
#endif
static int congenb = 0; /* Enable congestion control in the DP83840. */
static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
static int txdmacount = 0; /* Tx DMA burst length, 0-127, default 0. */
static int rxdmacount = 0; /* Rx DMA length, 0 means no preemption. */
/* I don't understand a byte in this structure. It was copied from the
* Linux kernel initialization for the eepro100. -- REW */
static struct ConfCmd {
@ -287,25 +264,16 @@ static struct ConfCmd {
0x3f, 0x05, }
};
#define TIME_OUT 1000000
static unsigned short eeprom [0x40];
/***********************************************************************/
/* Locally used functions */
/***********************************************************************/
/* Support function: mdio_write
*
* This probably writes to the "physical media interface chip".
* -- REW
*/
static int mdio_write(int phy_id, int location, int value)
{
int val, boguscnt = 64*4; /* <64 usec. to complete, typ 27 ticks */
@ -317,13 +285,12 @@ static int mdio_write(int phy_id, int location, int value)
val = inl(ioaddr + SCBCtrlMDI);
if (--boguscnt < 0) {
printf(" mdio_write() timed out with val = %8.8x.\n", val);
printf(" mdio_write() timed out with val = %X.\n", val);
}
} while (! (val & 0x10000000));
return val & 0xffff;
}
/* Support function: mdio_read
*
* This probably reads a register in the "physical media interface chip".
@ -338,54 +305,41 @@ static int mdio_read(int phy_id, int location)
val = inl(ioaddr + SCBCtrlMDI);
if (--boguscnt < 0) {
printf( " mdio_read() timed out with val = %8.8x.\n", val);
printf( " mdio_read() timed out with val = %X.\n", val);
}
} while (! (val & 0x10000000));
return val & 0xffff;
}
/* Support function: read_eeprom
* reads a value from the eeprom at a specified location.
* Arguments: location: address of the location to read from the eeprom.
* returns: value read from eeprom at location.
*/
static int read_eeprom(int location)
/* The fixes for the code were kindly provided by Dragan Stancevic
<visitor@valinux.com> to strictly follow Intel specifications of EEPROM
access timing.
The publicly available sheet 64486302 (sec. 3.1) specifies 1us access
interval for serial EEPROM. However, it looks like that there is an
additional requirement dictating larger udelay's in the code below.
2000/05/24 SAW */
static int do_eeprom_cmd(int cmd, int cmd_len)
{
int i;
unsigned short retval = 0;
int ee_addr = ioaddr + SCBeeprom;
int read_cmd = location | EE_READ_CMD;
unsigned retval = 0;
long ee_addr = ioaddr + SCBeeprom;
outw(EE_ENB & ~EE_CS, ee_addr);
outw(EE_ENB, ee_addr);
outw(EE_ENB, ee_addr); udelay(2);
outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
/* Shift the read command bits out. */
for (i = 10; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
outw(EE_ENB | dataval, ee_addr);
eeprom_delay(100);
outw(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
eeprom_delay(150);
outw(EE_ENB | dataval, ee_addr); /* Finish EEPROM a clock tick. */
eeprom_delay(250);
}
outw(EE_ENB, ee_addr);
/* Shift the command bits out. */
do {
short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
outw(dataval, ee_addr); udelay(2);
outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
} while (--cmd_len >= 0);
outw(EE_ENB, ee_addr); udelay(2);
for (i = 15; i >= 0; i--) {
outw(EE_ENB | EE_SHIFT_CLK, ee_addr);
eeprom_delay(100);
retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
outw(EE_ENB, ee_addr);
eeprom_delay(100);
}
/* Terminate the EEPROM access. */
outw(EE_ENB & ~EE_CS, ee_addr);
return retval;
/* Terminate the EEPROM access. */
outw(EE_ENB & ~EE_CS, ee_addr);
return retval;
}
static inline void whereami (const char *str)
{
#if 0
@ -394,15 +348,8 @@ static inline void whereami (const char *str)
#endif
}
/***********************************************************************/
/* Externally visible functions */
/***********************************************************************/
/* function: eepro100_reset / eth_reset
* resets the card. This is used to allow Linux to probe the card again
/* function: eepro100_reset
* resets the card. This is used to allow Etherboot to probe the card again
* from a "virginal" state....
* Arguments: none
*
@ -414,8 +361,6 @@ static void eepro100_reset(struct nic *nic)
outl(0, ioaddr + SCBPort);
}
/* function: eepro100_transmit
* This transmits a packet.
*
@ -429,8 +374,8 @@ static void eepro100_reset(struct nic *nic)
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];
unsigned char src_addr[6];
unsigned char dst_addr[ETH_ALEN];
unsigned char src_addr[ETH_ALEN];
unsigned short type;
} hdr;
unsigned short status;
@ -442,13 +387,12 @@ static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, un
outw(status & 0xfc00, ioaddr + SCBStatus);
#ifdef DEBUG
printf ("transmitting type %x packet (%d bytes). status = %x, cmd=%x\n",
printf ("transmitting type %hX packet (%d bytes). status = %hX, cmd=%hX\n",
t, s, status, inw (ioaddr + SCBCmd));
#endif
memcpy (&hdr.dst_addr, d, 6);
memcpy (&hdr.src_addr, nic->node_addr, 6);
memcpy (&hdr.dst_addr, d, ETH_ALEN);
memcpy (&hdr.src_addr, nic->node_addr, ETH_ALEN);
hdr.type = htons (t);
@ -474,18 +418,16 @@ static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, un
wait_for_cmd_done(ioaddr + SCBCmd);
s1 = inw (ioaddr + SCBStatus);
to = TIME_OUT;
while (!txfd.status && --to)
load_timer2(10*TICKS_PER_MS); /* timeout 10 ms for transmit */
while (!txfd.status && timer2_running())
/* Wait */;
s2 = inw (ioaddr + SCBStatus);
#ifdef DEBUG
printf ("Tx: Loop executed %d times.\n", TIME_OUT-to);
printf ("s1 = %x, s2 = %x.\n", s1, s2);
printf ("s1 = %hX, s2 = %hX.\n", s1, s2);
#endif
}
/* function: eepro100_poll / eth_poll
* This recieves a packet from the network.
*
@ -500,11 +442,8 @@ static void eepro100_transmit(struct nic *nic, const char *d, unsigned int t, un
static int eepro100_poll(struct nic *nic)
{
int to;
to = TIME_OUT;
while (!ACCESS(rxfd)status && --to)
/* Wait */;
if (!ACCESS(rxfd)status)
return 0;
/* Ok. We got a packet. Now restart the reciever.... */
ACCESS(rxfd)status = 0;
@ -513,22 +452,22 @@ static int eepro100_poll(struct nic *nic)
outw(INT_MASK | RX_START, ioaddr + SCBCmd);
wait_for_cmd_done(ioaddr + SCBCmd);
if (to) {
#ifdef DEBUG
printf ("Got a packet: Len = %d.\n", ACCESS(rxfd)count & 0x3fff);
printf ("Got a packet: Len = %d.\n", ACCESS(rxfd)count & 0x3fff);
#endif
nic->packetlen = ACCESS(rxfd)count & 0x3fff;
memcpy (nic->packet, ACCESS(rxfd)packet, nic->packetlen);
nic->packetlen = ACCESS(rxfd)count & 0x3fff;
memcpy (nic->packet, ACCESS(rxfd)packet, nic->packetlen);
#ifdef DEBUG
hd (nic->packet, 0x30);
hd (nic->packet, 0x30);
#endif
return 1;
} else
return 0;
return 1;
}
static void eepro100_disable(struct nic *nic)
{
/* See if this PartialReset solves the problem with interfering with
kernel operation after Etherboot hands over. - Ken 20001102 */
outl(2, ioaddr + SCBPort);
}
/* exported function: eepro100_probe / eth_probe
@ -541,63 +480,46 @@ static void eepro100_disable(struct nic *nic)
struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct pci_device *p)
{
u16 sum = 0;
int i, j, to;
unsigned short value;
int options;
int promisc;
unsigned short sum = 0;
int i;
int read_cmd, ee_size;
unsigned short value;
int options;
int promisc;
unsigned char pci_bus = 0;
unsigned short pci_command;
unsigned short new_command;
unsigned char pci_latency;
/* we cache only the first few words of the EEPROM data
be careful not to access beyond this array */
unsigned short eeprom[16];
if (probeaddrs == 0 || probeaddrs[0] == 0)
return 0;
if (probeaddrs == 0 || probeaddrs[0] == 0)
return 0;
ioaddr = probeaddrs[0] & ~3; /* Mask the bit that says "this is an io addr" */
ioaddr = probeaddrs[0] & ~3; /* Mask the bit that says "this is an io addr" */
adjust_pci_device(p);
/* Ok. Got one. Read the eeprom. */
for (j = 0, i = 0; i < 0x40; i++) {
value = read_eeprom(i);
eeprom[i] = value;
sum += value;
}
if ((do_eeprom_cmd(EE_READ_CMD << 24, 27) & 0xffe0000)
== 0xffe0000) {
ee_size = 0x100;
read_cmd = EE_READ_CMD << 24;
} else {
ee_size = 0x40;
read_cmd = EE_READ_CMD << 22;
}
/* From Matt Hortman <mbhortman@acpthinclient.com> */
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
*/
for (i = 0, sum = 0; i < ee_size; i++) {
unsigned short value = do_eeprom_cmd(read_cmd | (i << 16), 27);
if (i < (int)(sizeof(eeprom)/sizeof(eeprom[0])))
eeprom[i] = value;
sum += value;
}
pcibios_read_config_word(pci_bus, p->devfn, PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
if (pci_command != new_command) {
printf("\nThe PCI BIOS has not enabled this device!\nUpdating PCI command %x->%x. pci_bus %x pci_device_fn %x\n",
pci_command, new_command, pci_bus, p->devfn);
pcibios_write_config_word(pci_bus, p->devfn, PCI_COMMAND, new_command);
}
pcibios_read_config_byte(pci_bus, p->devfn, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < 32) {
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++) {
for (i=0;i<ETH_ALEN;i++) {
nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
printf ("%b%c", nic->node_addr[i] , i < 5?':':' ');
}
printf ("\n");
printf ("Ethernet addr: %!\n", nic->node_addr);
if (sum != 0xBABA)
printf("eepro100: Invalid EEPROM checksum %#4.4x, "
printf("eepro100: Invalid EEPROM checksum %#hX, "
"check settings before activating this device!\n", sum);
outl(0, ioaddr + SCBPort);
udelay (10);
@ -637,7 +559,6 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
outl(virt_to_bus(&(ACCESS(rxfd)status)), ioaddr + SCBPointer);
outw(INT_MASK | RX_START, ioaddr + SCBCmd);
/* INIT TX stuff. */
/* Base = 0 */
@ -654,7 +575,7 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
{
char *t = (char *)&txfd.tx_desc_addr;
for (i=0;i<6;i++)
for (i=0;i<ETH_ALEN;i++)
t[i] = nic->node_addr[i];
}
@ -667,13 +588,12 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
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(eeprom[6] & 0x1f, 23) | 0x0422;
if (congenb)
mdi_reg23 |= 0x0100;
printf(" DP83840 specific setup, setting register 23 to %x.\n",
printf(" DP83840 specific setup, setting register 23 to %hX.\n",
mdi_reg23);
mdio_write(eeprom[6] & 0x1f, 23, mdi_reg23);
}
@ -701,13 +621,10 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
whereami ("started TX thingy (config, iasetup).");
to = TIME_OUT;
while (!txfd.status && --to)
load_timer2(10*TICKS_PER_MS);
while (!txfd.status && timer2_running())
/* Wait */;
#ifdef DEBUG
printf ("\nLoop executed %d times.\n", TIME_OUT-to);
#endif
nic->reset = eepro100_reset;
nic->poll = eepro100_poll;
nic->transmit = eepro100_transmit;
@ -715,17 +632,6 @@ struct nic *eepro100_probe(struct nic *nic, unsigned short *probeaddrs, struct p
return nic;
}
static int loops_per_usec = 300; /* totally bogus value */
static void udelay (int val)
{
int c;
for(c=0; c<val*loops_per_usec; c++) {
/* Nothing */;
}
}
/*********************************************************************/
#ifdef DEBUG
@ -738,7 +644,7 @@ void hd (void *where, int n)
while (n > 0) {
printf ("%X ", where);
for (i=0;i < ( (n>16)?16:n);i++)
printf (" %b", ((char *)where)[i]);
printf (" %hhX", ((char *)where)[i]);
printf ("\n");
n -= 16;
where += 16;

View file

@ -5,6 +5,7 @@
#include "etherboot.h"
#include "nic.h"
#include "cards.h"
#include "timer.h"
#include "epic100.h"
#undef virt_to_bus
@ -15,8 +16,6 @@
#define PKT_BUF_SZ 1536 /* Size of each temporary Tx/Rx buffer.*/
#define TIME_OUT 1000000
/*
#define DEBUG_RX
#define DEBUG_TX
@ -83,7 +82,7 @@ static unsigned short eeprom[64];
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
#ifdef USE_LOWMEM_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
@ -170,7 +169,7 @@ epic100_probe(struct nic *nic, unsigned short *probeaddrs)
#if (EPIC_DEBUG > 1)
printf("EEPROM contents\n");
for (i = 0; i < 64; i++) {
printf(" %02x%s", eeprom[i], i % 16 == 15 ? "\n" : "");
printf(" %hhX%s", eeprom[i], i % 16 == 15 ? "\n" : "");
}
#endif
#endif
@ -180,10 +179,7 @@ epic100_probe(struct nic *nic, unsigned short *probeaddrs)
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(" I/O %#hX %! ", ioaddr, nic->node_addr);
/* Find the connected MII xcvrs. */
for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(phys); phy++) {
@ -215,7 +211,7 @@ epic100_probe(struct nic *nic, unsigned short *probeaddrs)
}
static void
epic100_open()
epic100_open(void)
{
int mii_reg5;
int full_duplex = 0;
@ -253,7 +249,7 @@ epic100_open()
/* Initialize the Rx and Tx rings. */
static void
epic100_init_ring()
epic100_init_ring(void)
{
int i;
char* p;
@ -300,16 +296,14 @@ epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
unsigned int len, const char *data)
{
unsigned short nstype;
unsigned short status;
char* txp;
int to;
int entry;
/* Calculate the next Tx descriptor entry. */
entry = cur_tx % TX_RING_SIZE;
if ((tx_ring[entry].status & TRING_OWN) == TRING_OWN) {
printf("eth_transmit: Unable to transmit. status=%x. Resetting...\n",
printf("eth_transmit: Unable to transmit. status=%hX. Resetting...\n",
tx_ring[entry].status);
epic100_open();
@ -318,13 +312,13 @@ epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
txp = (char*)tx_ring[entry].bufaddr;
memcpy(txp, destaddr, ETHER_ADDR_SIZE);
memcpy(txp + ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE);
memcpy(txp, destaddr, ETH_ALEN);
memcpy(txp + ETH_ALEN, nic->node_addr, ETH_ALEN);
nstype = htons(type);
memcpy(txp + 12, (char*)&nstype, 2);
memcpy(txp + ETHER_HDR_SIZE, data, len);
memcpy(txp + ETH_HLEN, data, len);
len += ETHER_HDR_SIZE;
len += ETH_HLEN;
/*
* Caution: the write order is important here,
@ -340,25 +334,13 @@ epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
/* Trigger an immediate transmit demand. */
outl(CR_QUEUE_TX, command);
to = TIME_OUT;
status = tx_ring[entry].status;
load_timer2(10*TICKS_PER_MS); /* timeout 10 ms for transmit */
while ((tx_ring[entry].status & TRING_OWN) && timer2_running())
/* Wait */;
while ( (status & TRING_OWN) && --to) {
status = tx_ring[entry].status;
}
if ((status & TRING_OWN) == 0) {
#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",
tx_ring[entry].status);
}
if ((tx_ring[entry].status & TRING_OWN) != 0)
printf("Oops, transmitter timeout, status=%hX\n",
tx_ring[entry].status);
}
/* function: epic100_poll / eth_poll
@ -376,35 +358,22 @@ epic100_transmit(struct nic *nic, const char *destaddr, unsigned int type,
static int
epic100_poll(struct nic *nic)
{
int to;
int entry;
int status;
int retcode;
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
printf("epic_poll: time out! status %x\n", status);
#endif
/* Restart Receiver */
outl(CR_START_RX | CR_QUEUE_RX, command);
return 0;
}
if ((status = rx_ring[entry].status & RRING_OWN) == RRING_OWN)
return (0);
/* 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);
printf("epic_poll: entry %d status %hX\n", entry, status);
#endif
cur_rx++;
if (status & 0x2000) {
printf("epic_poll: Giant packet\n");
retcode = 0;

View file

@ -1,3 +1,27 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* RULE: You must define the macro ``GRUB'' when including this header
file in GRUB code. */
/* Based on "src/etherboot.h" in etherboot-5.0.5. */
/**************************************************************************
ETHERBOOT - BOOTP/TFTP Bootstrap Program
@ -6,151 +30,75 @@ 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
#define RELOC 0
/* FIXME: Should be an option. */
# define BACKOFF_LIMIT 7
#endif /* GRUB */
#define BACKOFF_LIMIT 7
#include "osdep.h"
#include <osdep.h>
/* These could be customised for different languages perhaps */
#define ASK_PROMPT "Boot from (N)etwork or from (L)ocal? "
#define ANS_NETWORK 'N'
#define ANS_LOCAL 'L'
#ifndef ANS_DEFAULT /* in case left out in Makefile */
#define ANS_DEFAULT ANS_NETWORK
#endif
#define TAGGED_IMAGE /* eventually optional */
#if !defined(TAGGED_IMAGE) && !defined(AOUT_IMAGE) && !defined(ELF_IMAGE)
#define TAGGED_IMAGE /* choose at least one */
#endif
#ifdef GRUB
# define CTRL_C 3
#else /* ! GRUB */
# define ESC 0x1B
#endif /* ! GRUB */
#ifndef DEFAULT_BOOTFILE
#define DEFAULT_BOOTFILE "/tftpboot/kernel"
#endif
/* 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
#define CTRL_C 3
#ifndef MAX_TFTP_RETRIES
#define MAX_TFTP_RETRIES 20
# define MAX_TFTP_RETRIES 20
#endif
#ifndef MAX_BOOTP_RETRIES
#define MAX_BOOTP_RETRIES 20
# define MAX_BOOTP_RETRIES 20
#endif
#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
#endif
#define MAX_BOOTP_EXTLEN (ETH_FRAME_LEN - ETH_HLEN - \
sizeof (struct bootp_t))
#ifndef MAX_ARP_RETRIES
#define MAX_ARP_RETRIES 20
# define MAX_ARP_RETRIES 20
#endif
#ifndef MAX_RPC_RETRIES
#define MAX_RPC_RETRIES 20
# define MAX_RPC_RETRIES 20
#endif
#define TICKS_PER_SEC 18
/* Inter-packet retry in ticks */
#define TIMEOUT (10*TICKS_PER_SEC)
#define TIMEOUT (10 * TICKS_PER_SEC)
/* These settings have sense only if compiled with -DCONGESTED */
/* total retransmission timeout in ticks */
#define TFTP_TIMEOUT (30*TICKS_PER_SEC)
#define TFTP_TIMEOUT (30 * TICKS_PER_SEC)
/* packet retransmission timeout in ticks */
#define TFTP_REXMT (3*TICKS_PER_SEC)
#define TFTP_REXMT (3 * TICKS_PER_SEC)
#ifndef NULL
#define NULL ((void *)0)
# define NULL ((void *) 0)
#endif
#define TRUE 1
#define FALSE 0
/*
I'm moving towards the defined names in linux/if_ether.h for clarity.
The confusion between 60/64 and 1514/1518 arose because the NS8390
counts the 4 byte frame checksum in the incoming packet, but not
in the outgoing packet. 60/1514 are the correct numbers for most
if not all of the other NIC controllers. I will be retiring the
64/1518 defines in the lead-up to 5.0.
*/
#define ETHER_ADDR_SIZE 6 /* Size of Ethernet address */
#define ETHER_HDR_SIZE 14 /* Size of ethernet header */
#define ETH_MIN_PACKET 64
#define ETH_MAX_PACKET 1518
#define VENDOR_NONE 0
#define VENDOR_WD 1
#define VENDOR_NOVELL 2
#define VENDOR_3COM 3
#define VENDOR_3C509 4
#define VENDOR_CS89x0 5
#define FLAG_PIO 0x01
#define FLAG_16BIT 0x02
#define FLAG_790 0x04
#define ETH_ALEN 6 /* Size of Ethernet address */
#define ETH_HLEN 14 /* Size of ethernet header */
#define ETH_ZLEN 60 /* Minimum packet */
/*#define ETH_MIN_PACKET 64*/
#define ETH_FRAME_LEN 1514 /* Maximum packet */
/*#define ETH_MAX_PACKET 1518*/
#define ETH_MAX_MTU (ETH_FRAME_LEN - ETH_HLEN)
#define ARP_CLIENT 0
#define ARP_SERVER 1
@ -181,7 +129,7 @@ Author: Martin Renters
#define BOOTP_REQUEST 1
#define BOOTP_REPLY 2
#define TAG_LEN(p) (*((p)+1))
#define TAG_LEN(p) (*((p) + 1))
#define RFC1533_COOKIE 99, 130, 83, 99
#define RFC1533_PAD 0
#define RFC1533_NETMASK 1
@ -239,6 +187,7 @@ Author: Martin Renters
#define RFC2132_SRV_ID 54
#define RFC2132_PARAM_LIST 55
#define RFC2132_MAX_SIZE 57
#define RFC2132_VENDOR_CLASS_ID 60
#define DHCPDISCOVER 1
#define DHCPOFFER 2
@ -251,9 +200,6 @@ Author: Martin Renters
#define RFC1533_VENDOR_MAGIC 128
#define RFC1533_VENDOR_ADDPARM 129
#ifdef IMAGE_FREEBSD
#define RFC1533_VENDOR_HOWTO 132
#endif
#define RFC1533_VENDOR_MNUOPTS 160
#define RFC1533_VENDOR_SELECTION 176
#define RFC1533_VENDOR_MOTD 184
@ -261,11 +207,10 @@ Author: Martin Renters
#define RFC1533_VENDOR_IMG 192
#define RFC1533_VENDOR_NUMOFIMG 16
#ifdef GRUB
# define RFC1533_VENDOR_CONFIGFILE 150
#endif /* GRUB */
#define RFC1533_VENDOR_CONFIGFILE 150
#define RFC1533_END 255
#define BOOTP_VENDOR_LEN 64
#ifndef NO_DHCP_SUPPORT
#define DHCP_OPT_LEN 312
@ -294,129 +239,196 @@ Author: Martin Renters
#define AWAIT_RPC 4
#define AWAIT_QDRAIN 5 /* drain queue, process ARP requests */
typedef struct {
unsigned long s_addr;
} in_addr;
typedef struct
{
unsigned long s_addr;
}
in_addr;
struct arptable_t {
in_addr ipaddr;
unsigned char node[6];
struct arptable_t
{
in_addr ipaddr;
unsigned char node[6];
};
/*
* A pity sipaddr and tipaddr are not longword aligned or we could use
* in_addr. No, I don't want to use #pragma packed.
*/
struct arprequest {
unsigned short hwtype;
unsigned short protocol;
char hwlen;
char protolen;
unsigned short opcode;
char shwaddr[6];
char sipaddr[4];
char thwaddr[6];
char tipaddr[4];
struct arprequest
{
unsigned short hwtype;
unsigned short protocol;
char hwlen;
char protolen;
unsigned short opcode;
char shwaddr[6];
char sipaddr[4];
char thwaddr[6];
char tipaddr[4];
};
struct iphdr {
char verhdrlen;
char service;
unsigned short len;
unsigned short ident;
unsigned short frags;
char ttl;
char protocol;
unsigned short chksum;
in_addr src;
in_addr dest;
struct iphdr
{
char verhdrlen;
char service;
unsigned short len;
unsigned short ident;
unsigned short frags;
char ttl;
char protocol;
unsigned short chksum;
in_addr src;
in_addr dest;
};
struct udphdr {
unsigned short src;
unsigned short dest;
unsigned short len;
unsigned short chksum;
struct udphdr
{
unsigned short src;
unsigned short dest;
unsigned short len;
unsigned short chksum;
};
struct bootp_t {
struct iphdr ip;
struct udphdr udp;
char bp_op;
char bp_htype;
char bp_hlen;
char bp_hops;
unsigned long bp_xid;
unsigned short bp_secs;
unsigned short unused;
in_addr bp_ciaddr;
in_addr bp_yiaddr;
in_addr bp_siaddr;
in_addr bp_giaddr;
char bp_hwaddr[16];
char bp_sname[64];
char bp_file[128];
/* Format of a bootp packet. */
struct bootp_t
{
char bp_op;
char bp_htype;
char bp_hlen;
char bp_hops;
unsigned long bp_xid;
unsigned short bp_secs;
unsigned short unused;
in_addr bp_ciaddr;
in_addr bp_yiaddr;
in_addr bp_siaddr;
in_addr bp_giaddr;
char bp_hwaddr[16];
char bp_sname[64];
char bp_file[128];
#ifdef NO_DHCP_SUPPORT
char bp_vend[BOOTP_VENDOR_LEN];
char bp_vend[BOOTP_VENDOR_LEN];
#else
char bp_vend[DHCP_OPT_LEN];
char bp_vend[DHCP_OPT_LEN];
#endif /* NO_DHCP_SUPPORT */
};
struct bootpd_t {
struct bootp_t bootp_reply;
unsigned char bootp_extension[MAX_BOOTP_EXTLEN];
/* Format of a bootp IP packet. */
struct bootpip_t
{
struct iphdr ip;
struct udphdr udp;
struct bootp_t bp;
};
struct tftp_t {
struct iphdr ip;
struct udphdr udp;
unsigned short opcode;
union {
char rrq[TFTP_DEFAULTSIZE_PACKET];
struct {
unsigned short block;
char download[TFTP_MAX_PACKET];
} data;
struct {
unsigned short block;
} ack;
struct {
unsigned short errcode;
char errmsg[TFTP_DEFAULTSIZE_PACKET];
} err;
struct {
char data[TFTP_DEFAULTSIZE_PACKET+2];
} oack;
} u;
/* Format of bootp packet with extensions. */
struct bootpd_t
{
struct bootp_t bootp_reply;
unsigned char bootp_extension[MAX_BOOTP_EXTLEN];
};
struct tftp_t
{
struct iphdr ip;
struct udphdr udp;
unsigned short opcode;
union
{
char rrq[TFTP_DEFAULTSIZE_PACKET];
struct
{
unsigned short block;
char download[TFTP_MAX_PACKET];
}
data;
struct
{
unsigned short block;
}
ack;
struct
{
unsigned short errcode;
char errmsg[TFTP_DEFAULTSIZE_PACKET];
}
err;
struct
{
char data[TFTP_DEFAULTSIZE_PACKET+2];
}
oack;
}
u;
};
/* Define a smaller tftp packet solely for making requests to conserve stack
512 bytes should be enough. */
struct tftpreq_t
{
struct iphdr ip;
struct udphdr udp;
unsigned short opcode;
union
{
char rrq[512];
struct
{
unsigned short block;
}
ack;
struct
{
unsigned short errcode;
char errmsg[512-2];
}
err;
}
u;
};
#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;
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
@ -446,179 +458,85 @@ struct rpc_t {
#define NFS_READ_SIZE 1024
#define FLOPPY_BOOT_LOCATION 0x7c00
/* Must match offsets in loader.S */
#define ROM_SEGMENT 0x1fa
#define ROM_LENGTH 0x1fc
#define ROM_INFO_LOCATION 0x7dfa
#define ROM_INFO_LOCATION (FLOPPY_BOOT_LOCATION + ROM_SEGMENT)
/* at end of floppy boot block */
struct rom_info {
unsigned short rom_segment;
unsigned short rom_length;
struct rom_info
{
unsigned short rom_segment;
unsigned short rom_length;
};
static inline int
rom_address_ok (struct rom_info *rom, int assigned_rom_segment)
{
return (assigned_rom_segment < 0xC000
|| assigned_rom_segment == rom->rom_segment);
}
/* Define a type for passing info to a loaded program. */
struct ebinfo
{
unsigned char major, minor; /* Version */
unsigned short flags; /* Bit flags */
};
/***************************************************************************
External prototypes
***************************************************************************/
/* main.c */
#ifdef GRUB
extern void print_network_configuration P((void));
extern int ifconfig P((char *ip, char *sm, char *gw, char *svr));
#endif /* GRUB */
#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 downloadkernel P((unsigned char *, int, int, int));
extern int tftp P((const char *name, int (*)(unsigned char *, int, int, int)));
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, 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));
extern void print_network_configuration (void);
extern int ifconfig (char *ip, char *sm, char *gw, char *svr);
extern int udp_transmit (unsigned long destip, unsigned int srcsock,
unsigned int destsock, int len, const void *buf);
extern int await_reply (int type, int ival, void *ptr, int timeout);
extern int decode_rfc1533 (unsigned char *, int, int, int);
extern long rfc2131_sleep_interval (int base, int exp);
extern void cleanup (void);
extern int rarp (void);
extern int bootp (void);
extern void cleanup_net (void);
/* 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));
extern void show_motd P((void));
extern void parse_menuopts P((char *,int));
extern int getoptvalue P((char **, int *, int *));
extern void selectImage P((char **));
/* osloader.c */
#if defined(AOUT_IMAGE) || defined(ELF_IMAGE)
extern int howto;
#endif
extern int os_download P((unsigned int, unsigned char *,unsigned int));
#endif /* ! GRUB */
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);
/* misc.c */
extern void twiddle P((void));
extern void sleep P((int secs));
#ifndef GRUB
extern int strcasecmp P((char *a, char *b));
extern char *substr P((char *a, char *b));
#endif /* ! GRUB */
extern int getdec P((char **));
#ifndef GRUB
extern void printf P((const char *, ...));
extern char *sprintf P((char *, const char *, ...));
#endif /* ! GRUB */
extern int inet_aton P((char *p, in_addr *i));
#ifndef GRUB
extern void gateA20_set P((void));
extern void gateA20_unset P((void));
extern void putchar P((int));
extern int getchar P((void));
extern int iskey P((void));
/* start*.S */
extern int getc P((void));
extern void putc P((int));
extern int ischar P((void));
extern int getshift 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 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 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));
extern void md5_done P((unsigned char *buf));
/* floppy.c */
extern int bootdisk P((int dev,int part));
#endif /* ! GRUB */
extern void twiddle (void);
extern void sleep (int secs);
extern int getdec (char **s);
extern void etherboot_printf (const char *, ...);
extern int etherboot_sprintf (char *, const char *, ...);
extern int inet_aton (char *p, in_addr *i);
/***************************************************************************
External variables
***************************************************************************/
/* main.c */
#ifdef GRUB
extern int ip_abort;
extern int network_ready;
#endif /* GRUB */
#ifndef GRUB
extern const char *kernel;
extern char kernel_buf[128];
#endif /* ! GRUB */
extern struct rom_info rom;
#ifndef GRUB
extern int hostnamelen;
extern unsigned long netmask;
extern int jmp_bootmenu[10];
#endif /* ! GRUB */
extern struct arptable_t arptable[MAX_ARP];
#ifndef GRUB
#ifdef IMAGE_MENU
extern char *motd[RFC1533_VENDOR_NUMOFMOTD];
extern int menutmo,menudefault;
extern unsigned char *defparams;
extern int defparams_max;
#endif
#endif /* ! GRUB */
#if defined(ETHERBOOT32) && !defined(INTERNAL_BOOTP_DATA)
#define BOOTP_DATA_ADDR ((struct bootpd_t *)0x93C00)
#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 */
/* Local hack - define some macros to use etherboot source files "as is". */
#ifndef GRUB
/* created by linker */
extern char _start[], _edata[], _end[];
#endif /* ! GRUB */
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
# undef printf
# define printf etherboot_printf
# undef sprintf
# define sprintf etherboot_sprintf
#endif /* GRUB */

421
netboot/fa311.c Normal file
View file

@ -0,0 +1,421 @@
/*
Driver for the National Semiconductor DP83810 Ethernet controller.
Portions Copyright (C) 2001 Inprimis Technologies, Inc.
http://www.inprimis.com/
This driver is based (heavily) on the Linux driver for this chip
which is copyright 1999-2001 by Donald Becker.
This software has no warranties expressed or implied for any
purpose.
This software may be used and distributed according to the terms of
the GNU General Public License (GPL), incorporated herein by reference.
Drivers based on or derived from this code fall under the GPL and must
retain the authorship, copyright and license notice. This file is not
a complete program and may only be used when the entire operating
system is licensed under the GPL. License for under other terms may be
available. Contact the original author for details.
The original author may be reached as becker@scyld.com, or at
Scyld Computing Corporation
410 Severn Ave., Suite 210
Annapolis MD 21403
*/
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#undef virt_to_bus
#define virt_to_bus(x) ((unsigned long)x)
#define cpu_to_le32(val) (val)
#define le32_to_cpu(val) (val)
#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr))
#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr))
#define TX_RING_SIZE 1
#define RX_RING_SIZE 4
#define TIME_OUT 1000000
#define PKT_BUF_SZ 1536
/* Offsets to the device registers. */
enum register_offsets {
ChipCmd=0x00, ChipConfig=0x04, EECtrl=0x08, PCIBusCfg=0x0C,
IntrStatus=0x10, IntrMask=0x14, IntrEnable=0x18,
TxRingPtr=0x20, TxConfig=0x24,
RxRingPtr=0x30, RxConfig=0x34,
WOLCmd=0x40, PauseCmd=0x44, RxFilterAddr=0x48, RxFilterData=0x4C,
BootRomAddr=0x50, BootRomData=0x54, StatsCtrl=0x5C, StatsData=0x60,
RxPktErrs=0x60, RxMissed=0x68, RxCRCErrs=0x64,
};
/* Bit in ChipCmd. */
enum ChipCmdBits {
ChipReset=0x100, RxReset=0x20, TxReset=0x10, RxOff=0x08, RxOn=0x04,
TxOff=0x02, TxOn=0x01,
};
/* Bits in the interrupt status/mask registers. */
enum intr_status_bits {
IntrRxDone=0x0001, IntrRxIntr=0x0002, IntrRxErr=0x0004, IntrRxEarly=0x0008,
IntrRxIdle=0x0010, IntrRxOverrun=0x0020,
IntrTxDone=0x0040, IntrTxIntr=0x0080, IntrTxErr=0x0100,
IntrTxIdle=0x0200, IntrTxUnderrun=0x0400,
StatsMax=0x0800, LinkChange=0x4000, WOLPkt=0x2000,
RxResetDone=0x1000000, TxResetDone=0x2000000,
IntrPCIErr=0x00f00000, IntrNormalSummary=0x0251, IntrAbnormalSummary=0xED20,
};
/* Bits in the RxMode register. */
enum rx_mode_bits {
AcceptErr=0x20, AcceptRunt=0x10, AcceptBroadcast=0xC0000000,
AcceptMulticast=0x00200000, AcceptAllMulticast=0x20000000,
AcceptAllPhys=0x10000000, AcceptMyPhys=0x08000000,
};
/* Bits in network_desc.status */
enum desc_status_bits {
DescOwn=0x80000000, DescMore=0x40000000, DescIntr=0x20000000,
DescNoCRC=0x10000000,
DescPktOK=0x08000000, RxTooLong=0x00400000,
};
/* The Rx and Tx buffer descriptors. */
struct netdev_desc {
u32 next_desc;
s32 cmd_status;
u32 addr;
};
static struct FA311_DEV {
unsigned int ioaddr;
unsigned short vendor;
unsigned short device;
unsigned int cur_rx;
unsigned int cur_tx;
unsigned int rx_buf_sz;
volatile struct netdev_desc *rx_head_desc;
volatile struct netdev_desc rx_ring[RX_RING_SIZE] __attribute__ ((aligned (4)));
volatile struct netdev_desc tx_ring[TX_RING_SIZE] __attribute__ ((aligned (4)));
} fa311_dev;
static int eeprom_read(long ioaddr, int location);
static void init_ring(struct FA311_DEV *dev);
static void fa311_reset(struct nic *nic);
static int fa311_poll(struct nic *nic);
static void fa311_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p);
static void fa311_disable(struct nic *nic);
static char rx_packet[PKT_BUF_SZ * RX_RING_SIZE] __attribute__ ((aligned (4)));
static char tx_packet[PKT_BUF_SZ * TX_RING_SIZE] __attribute__ ((aligned (4)));
struct nic * fa311_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci)
{
int prev_eedata;
int i;
int duplex;
int tx_config;
int rx_config;
unsigned char macaddr[6];
unsigned char mactest;
unsigned char pci_bus = 0;
struct FA311_DEV* dev = &fa311_dev;
if (io_addrs == 0 || *io_addrs == 0)
return (0);
memset(dev, 0, sizeof(*dev));
dev->vendor = pci->vendor;
dev->device = pci->dev_id;
dev->ioaddr = pci->membase;
/* Work around the dropped serial bit. */
prev_eedata = eeprom_read(dev->ioaddr, 6);
for (i = 0; i < 3; i++) {
int eedata = eeprom_read(dev->ioaddr, i + 7);
macaddr[i*2] = (eedata << 1) + (prev_eedata >> 15);
macaddr[i*2+1] = eedata >> 7;
prev_eedata = eedata;
}
mactest = 0;
for (i = 0; i < 6; i++)
mactest |= macaddr[i];
if (mactest == 0)
return (0);
for (i = 0; i < 6; i++)
nic->node_addr[i] = macaddr[i];
printf("%! ", nic->node_addr);
adjust_pci_device(pci);
fa311_reset(nic);
nic->reset = fa311_reset;
nic->disable = fa311_disable;
nic->poll = fa311_poll;
nic->transmit = fa311_transmit;
init_ring(dev);
writel(virt_to_bus(dev->rx_ring), dev->ioaddr + RxRingPtr);
writel(virt_to_bus(dev->tx_ring), dev->ioaddr + TxRingPtr);
for (i = 0; i < 6; i += 2)
{
writel(i, dev->ioaddr + RxFilterAddr);
writew(macaddr[i] + (macaddr[i+1] << 8),
dev->ioaddr + RxFilterData);
}
/* Initialize other registers. */
/* Configure for standard, in-spec Ethernet. */
if (readl(dev->ioaddr + ChipConfig) & 0x20000000)
{ /* Full duplex */
tx_config = 0xD0801002;
rx_config = 0x10000020;
}
else
{
tx_config = 0x10801002;
rx_config = 0x0020;
}
writel(tx_config, dev->ioaddr + TxConfig);
writel(rx_config, dev->ioaddr + RxConfig);
duplex = readl(dev->ioaddr + ChipConfig) & 0x20000000 ? 1 : 0;
if (duplex) {
rx_config |= 0x10000000;
tx_config |= 0xC0000000;
} else {
rx_config &= ~0x10000000;
tx_config &= ~0xC0000000;
}
writew(tx_config, dev->ioaddr + TxConfig);
writew(rx_config, dev->ioaddr + RxConfig);
writel(AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys,
dev->ioaddr + RxFilterAddr);
writel(RxOn | TxOn, dev->ioaddr + ChipCmd);
writel(4, dev->ioaddr + StatsCtrl); /* Clear Stats */
return nic;
}
static void fa311_reset(struct nic *nic)
{
u32 chip_config;
struct FA311_DEV* dev = &fa311_dev;
/* Reset the chip to erase previous misconfiguration. */
outl(ChipReset, dev->ioaddr + ChipCmd);
if ((readl(dev->ioaddr + ChipConfig) & 0xe000) != 0xe000)
{
chip_config = readl(dev->ioaddr + ChipConfig);
}
}
static int fa311_poll(struct nic *nic)
{
s32 desc_status;
int to;
int entry;
int retcode;
struct FA311_DEV* dev = &fa311_dev;
retcode = 0;
entry = dev->cur_rx;
to = TIME_OUT;
while (to != 0)
{
desc_status = dev->rx_ring[entry].cmd_status;
if ((desc_status & DescOwn) != 0)
break;
else
--to;
}
if (to != 0)
{
readl(dev->ioaddr + IntrStatus); /* clear interrrupt bits */
/* driver owns the next entry it's a new packet. Send it up. */
if ((desc_status & (DescMore|DescPktOK|RxTooLong)) == DescPktOK)
{
nic->packetlen = (desc_status & 0x0fff) - 4; /* Omit CRC size. */
memcpy(nic->packet, (char*)(dev->rx_ring[entry].addr), nic->packetlen);
retcode = 1;
}
/* Give the descriptor back to the chip */
dev->rx_ring[entry].cmd_status = cpu_to_le32(dev->rx_buf_sz);
dev->cur_rx++;
if (dev->cur_rx >= RX_RING_SIZE)
dev->cur_rx = 0;
dev->rx_head_desc = &dev->rx_ring[dev->cur_rx];
}
/* Restart Rx engine if stopped. */
writel(RxOn, dev->ioaddr + ChipCmd);
return retcode;
}
static void fa311_transmit(struct nic *nic, const char *destaddr, unsigned int type, unsigned int len, const char *data)
{
unsigned short nstype;
s32 desc_status;
int to;
int entry;
char* txp;
unsigned char* s;
struct FA311_DEV* dev = &fa311_dev;
/* Calculate the next Tx descriptor entry. */
entry = dev->cur_tx;
txp = (char*)(dev->tx_ring[entry].addr);
memcpy(txp, destaddr, ETH_ALEN);
memcpy(txp + ETH_ALEN, nic->node_addr, ETH_ALEN);
nstype = htons(type);
memcpy(txp + 12, (char*)&nstype, 2);
memcpy(txp + ETH_HLEN, data, len);
len += ETH_HLEN;
/* pad frame */
if (len < ETH_ZLEN)
{
s = (unsigned char*)(txp+len);
while (s < (unsigned char*)(txp+ETH_ZLEN))
*s++ = 0;
len = ETH_ZLEN;
}
dev->tx_ring[entry].cmd_status = cpu_to_le32(DescOwn | len);
dev->cur_tx++;
if (dev->cur_tx >= TX_RING_SIZE)
dev->cur_tx = 0;
/* Wake the potentially-idle transmit channel. */
writel(TxOn, dev->ioaddr + ChipCmd);
/* wait for tranmission to complete */
to = TIME_OUT;
while (to != 0)
{
desc_status = dev->tx_ring[entry].cmd_status;
if ((desc_status & DescOwn) == 0)
break;
else
--to;
}
readl(dev->ioaddr + IntrStatus); /* clear interrrupt bits */
return;
}
static void fa311_disable(struct nic *nic)
{
struct FA311_DEV* dev = &fa311_dev;
/* Stop the chip's Tx and Rx processes. */
writel(RxOff | TxOff, dev->ioaddr + ChipCmd);
}
/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.
The EEPROM code is for the common 93c06/46 EEPROMs with 6 bit addresses. */
/* Delay between EEPROM clock transitions.
No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
made udelay() unreliable.
The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
depricated.
*/
#define eeprom_delay(ee_addr) inl(ee_addr)
enum EEPROM_Ctrl_Bits {
EE_ShiftClk=0x04, EE_DataIn=0x01, EE_ChipSelect=0x08, EE_DataOut=0x02,
};
#define EE_Write0 (EE_ChipSelect)
#define EE_Write1 (EE_ChipSelect | EE_DataIn)
/* The EEPROM commands include the alway-set leading bit. */
enum EEPROM_Cmds {
EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
};
static int eeprom_read(long addr, int location)
{
int i;
int retval = 0;
int ee_addr = addr + EECtrl;
int read_cmd = location | EE_ReadCmd;
writel(EE_Write0, ee_addr);
/* Shift the read command bits out. */
for (i = 10; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
writel(dataval, ee_addr);
eeprom_delay(ee_addr);
writel(dataval | EE_ShiftClk, ee_addr);
eeprom_delay(ee_addr);
}
writel(EE_ChipSelect, ee_addr);
eeprom_delay(ee_addr);
for (i = 0; i < 16; i++) {
writel(EE_ChipSelect | EE_ShiftClk, ee_addr);
eeprom_delay(ee_addr);
retval |= (readl(ee_addr) & EE_DataOut) ? 1 << i : 0;
writel(EE_ChipSelect, ee_addr);
eeprom_delay(ee_addr);
}
/* Terminate the EEPROM access. */
writel(EE_Write0, ee_addr);
writel(0, ee_addr);
return retval;
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void init_ring(struct FA311_DEV *dev)
{
int i;
dev->cur_rx = 0;
dev->cur_tx = 0;
dev->rx_buf_sz = PKT_BUF_SZ;
dev->rx_head_desc = &dev->rx_ring[0];
/* Initialize all Rx descriptors. */
for (i = 0; i < RX_RING_SIZE; i++) {
dev->rx_ring[i].next_desc = virt_to_le32desc(&dev->rx_ring[i+1]);
dev->rx_ring[i].cmd_status = DescOwn;
}
/* Mark the last entry as wrapping the ring. */
dev->rx_ring[i-1].next_desc = virt_to_le32desc(&dev->rx_ring[0]);
/* Fill in the Rx buffers. Handle allocation failure gracefully. */
for (i = 0; i < RX_RING_SIZE; i++) {
dev->rx_ring[i].addr = (u32)(&rx_packet[PKT_BUF_SZ * i]);
dev->rx_ring[i].cmd_status = cpu_to_le32(dev->rx_buf_sz);
}
for (i = 0; i < TX_RING_SIZE; i++) {
dev->tx_ring[i].next_desc = virt_to_le32desc(&dev->tx_ring[i+1]);
dev->tx_ring[i].cmd_status = 0;
}
dev->tx_ring[i-1].next_desc = virt_to_le32desc(&dev->tx_ring[0]);
for (i = 0; i < TX_RING_SIZE; i++)
dev->tx_ring[i].addr = (u32)(&tx_packet[PKT_BUF_SZ * i]);
return;
}

View file

@ -30,6 +30,7 @@ Author: Martin Renters
#include <filesys.h>
#define GRUB 1
#include <etherboot.h>
#include <nic.h>
@ -56,13 +57,15 @@ buf_fill (int abort)
while (! buf_eof && (buf_read + packetsize <= FSYS_BUFLEN))
{
struct tftp_t *tr;
long timeout;
#ifdef CONGESTED
if (! await_reply (AWAIT_TFTP, iport, NULL,
block ? TFTP_REXMT : TIMEOUT))
timeout = rfc2131_sleep_interval (block ? TFTP_REXMT : TIMEOUT, retry);
#else
if (! await_reply (AWAIT_TFTP, iport, NULL, TIMEOUT))
timeout = rfc2131_sleep_interval (TIMEOUT, retry);
#endif
if (! await_reply (AWAIT_TFTP, iport, NULL, timeout))
{
if (ip_abort)
return 0;
@ -73,7 +76,6 @@ buf_fill (int abort)
#ifdef TFTP_DEBUG
grub_printf ("Maybe initial request was lost.\n");
#endif
rfc951_sleep (retry);
if (! udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
++iport, TFTP_PORT, len, &tp))
return 0;
@ -98,7 +100,7 @@ buf_fill (int abort)
return 0;
}
tr = (struct tftp_t *) &nic.packet[ETHER_HDR_SIZE];
tr = (struct tftp_t *) &nic.packet[ETH_HLEN];
if (tr->opcode == ntohs (TFTP_ERROR))
{
grub_printf ("TFTP error %d (%s)\n",
@ -161,7 +163,9 @@ buf_fill (int abort)
tp.u.err.errcode = 8;
len = (grub_sprintf ((char *) tp.u.err.errmsg,
"RFC1782 error")
+ TFTP_MIN_PACKET + 1);
+ sizeof (tp.ip) + sizeof (tp.udp)
+ sizeof (tp.opcode) + sizeof (tp.u.err.errcode)
+ 1);
udp_transmit (arptable[ARP_SERVER].ipaddr.s_addr,
iport, ntohs (tr->udp.src),
len, &tp);
@ -413,7 +417,7 @@ tftp_dir (char *dirname)
grub_printf ("tftp_dir (%s)\n", dirname);
#endif
/* In TFTP, there is no way to know what files exis. */
/* In TFTP, there is no way to know what files exist. */
if (print_possibilities)
return 1;
@ -429,7 +433,7 @@ tftp_dir (char *dirname)
len = (grub_sprintf ((char *) tp.u.rrq,
"%s%coctet%cblksize%c%d%ctsize%c0",
dirname, 0, 0, 0, TFTP_MAX_PACKET, 0, 0)
+ sizeof (struct iphdr) + sizeof (struct udphdr) + 2 + 1);
+ sizeof (tp.ip) + sizeof (tp.udp) + sizeof (tp.opcode) + 1);
/* Restore the original DIRNAME. */
dirname[grub_strlen (dirname)] = ch;
/* Save the TFTP packet so that we can reopen the file later. */

View file

@ -14,6 +14,9 @@ Ken Yap, January 1998
#include "etherboot.h"
#include "nic.h"
#include "cards.h"
#include "timer.h"
#define udelay(n) waiton_timer2(((n)*TICKS_PER_MS)/1000)
/* Sources of information:
@ -273,12 +276,7 @@ static void setup_rx_buffers(struct nic *nic)
rx_cmd[2] = cur_rx_buf + RX_BUF_SIZE;
rx_cmd[3] = cur_rx_buf + 22;
rx_cmd[13] = cur_rx_buf + 0x20 + scb_base;
#ifdef ETHERBOOT32
memcpy((char *)write_ptr, (char *)rx_cmd, sizeof(rx_cmd));
#endif
#ifdef ETHERBOOT16
memcpyf(write_ptr, (char *)rx_cmd, sizeof(rx_cmd));
#endif
rx_tail = cur_rx_buf;
cur_rx_buf += RX_BUF_SIZE;
} while (cur_rx_buf <= RX_BUF_END - RX_BUF_SIZE);
@ -287,27 +285,14 @@ static void setup_rx_buffers(struct nic *nic)
write_ptr = mem_start + rx_tail;
rx_cmd[1] = 0xC000;
rx_cmd[2] = rx_head;
#ifdef ETHERBOOT32
memcpy((char *)write_ptr, (char *)rx_cmd, sizeof(unsigned short) * 3);
#endif
#ifdef ETHERBOOT16
memcpyf(write_ptr, (char *)rx_cmd, sizeof(unsigned short) * 3);
#endif
}
static void ack_status(void)
{
unsigned short cmd, status;
#ifdef ETHERBOOT32
unsigned short *shmem = (short *)mem_start;
#endif
#ifdef ETHERBOOT16
unsigned short shmem[CONFIG_CMD>>1];
#endif
#ifdef ETHERBOOT16
read_mem(mem_start, shmem);
#endif
cmd = (status = shmem[iSCB_STATUS>>1]) & 0xf000;
if (status & 0x100) /* CU suspended? */
cmd |= CUC_RESUME;
@ -320,11 +305,8 @@ static void ack_status(void)
if (cmd == 0) /* Nothing to do */
return;
shmem[iSCB_CMD>>1] = cmd;
#ifdef ETHERBOOT16
memcpyf(mem_start, shmem, sizeof(shmem));
#endif
#if defined(DEBUG)
printf("Status %x Command %x\n", status, cmd);
printf("Status %hX Command %hX\n", status, cmd);
#endif
outb(0, ioaddr + I82586_ATTN);
}
@ -336,12 +318,7 @@ RESET - Reset adapter
static void i82586_reset(struct nic *nic)
{
unsigned long time;
#ifdef ETHERBOOT32
unsigned short *shmem = (short *)mem_start;
#endif
#ifdef ETHERBOOT16
unsigned short shmem[CONFIG_CMD>>1];
#endif
/* put the card in its initial state */
@ -358,16 +335,9 @@ static void i82586_reset(struct nic *nic)
/* Write the words at 0xfff6. */
/* Write the words at 0x0000. */
/* Fill in the station address. */
#ifdef ETHERBOOT32
memcpy((char *)(mem_end - 10), (char *)init_words, 10);
memcpy((char *)mem_start, (char *)&init_words[5], sizeof(init_words) - 10);
memcpy((char *)mem_start + SA_OFFSET, nic->node_addr, ETHER_ADDR_SIZE);
#endif
#ifdef ETHERBOOT16
memcpyf(mem_end - 10, (char *)init_words, 10);
memcpyf(mem_start, (char *)&init_words[5], sizeof(init_words) - 10);
memcpyf(mem_start + SA_OFFSET, nic->node_addr, ETHER_ADDR_SIZE);
#endif
memcpy((char *)mem_start + SA_OFFSET, nic->node_addr, ETH_ALEN);
setup_rx_buffers(nic);
#ifdef INCLUDE_3C507
@ -380,14 +350,11 @@ static void i82586_reset(struct nic *nic)
outb(0, ioaddr + I82586_ATTN);
time = currticks() + TICKS_PER_SEC; /* allow 1 second to init */
while (
#ifdef ETHERBOOT16
read_mem(mem_start, shmem),
#endif
shmem[iSCB_STATUS>>1] == 0)
{
if (currticks() > time)
{
printf("i82586 initialisation timed out with status %x, cmd %x\n",
printf("i82586 initialisation timed out with status %hX, cmd %hX\n",
shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
break;
}
@ -400,10 +367,7 @@ static void i82586_reset(struct nic *nic)
outb(0x80, ioaddr + MISC_CTRL);
#endif
#if defined(DEBUG)
#ifdef ETHERBOOT16
read_mem(mem_start, shmem);
#endif
printf("i82586 status %x, cmd %x\n",
printf("i82586 status %hX, cmd %hX\n",
shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
#endif
}
@ -416,18 +380,10 @@ static int i82586_poll(struct nic *nic)
int status;
unsigned short rfd_cmd, next_rx_frame, data_buffer_addr,
frame_status, pkt_len;
#ifdef ETHERBOOT32
unsigned short *shmem = (short *)mem_start + rx_head;
#endif
#ifdef ETHERBOOT16
unsigned short shmem[16];
#endif
/* return true if there's an ethernet packet ready to read */
if (
#ifdef ETHERBOOT16
read_mem(mem_start + rx_head, shmem),
#endif
((frame_status = shmem[0]) & 0x8000) == 0)
return (0); /* nope */
rfd_cmd = shmem[1];
@ -444,14 +400,9 @@ static int i82586_poll(struct nic *nic)
{
/* We have a frame, copy it to our buffer */
pkt_len &= 0x3FFF;
#ifdef ETHERBOOT32
memcpy(nic->packet, (char *)mem_start + rx_head + 0x20, pkt_len);
#endif
#ifdef ETHERBOOT16
fmemcpy(nic->packet, mem_start + rx_head + 0x20, pkt_len);
#endif
/* Only packets not from ourself */
if (memcmp(nic->packet + ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE) != 0)
if (memcmp(nic->packet + ETH_ALEN, nic->node_addr, ETH_ALEN) != 0)
{
nic->packetlen = pkt_len;
status = 1;
@ -460,14 +411,7 @@ static int i82586_poll(struct nic *nic)
/* Clear the status word and set EOL on Rx frame */
shmem[0] = 0;
shmem[1] = 0xC000;
#ifdef ETHERBOOT16
memcpyf(mem_start + rx_head, shmem, sizeof(unsigned short) * 2);
/* Clear the EOL on previous RFD */
memcpyf(mem_start + rx_tail + 2, shmem, sizeof(unsigned short));
#endif
#ifdef ETHERBOOT32
*(short *)(mem_start + rx_tail + 2) = 0;
#endif
rx_tail = rx_head;
rx_head = next_rx_frame;
ack_status();
@ -499,66 +443,35 @@ static void i82586_transmit(
CmdNOp, /* Nop command */
TX_BUF_START+16 /* Next is myself */
};
#ifdef ETHERBOOT32
unsigned short *shmem = (short *)mem_start + TX_BUF_START;
#endif
#ifdef ETHERBOOT16
unsigned short shmem[11];
#endif
/* send the packet to destination */
/* adjust some contents */
type = htons(t);
if (s < ETH_MIN_PACKET)
s = ETH_MIN_PACKET;
tx_cmd[4] = (s + ETHER_HDR_SIZE) | 0x8000;
if (s < ETH_ZLEN)
s = ETH_ZLEN;
tx_cmd[4] = (s + ETH_HLEN) | 0x8000;
tx_cmd[6] = TX_BUF_START + 22 + scb_base;
bptr = mem_start + TX_BUF_START;
#ifdef ETHERBOOT32
memcpy((char *)bptr, (char *)tx_cmd, sizeof(tx_cmd));
bptr += sizeof(tx_cmd);
memcpy((char *)bptr, d, ETHER_ADDR_SIZE);
bptr += ETHER_ADDR_SIZE;
memcpy((char *)bptr, nic->node_addr, ETHER_ADDR_SIZE);
bptr += ETHER_ADDR_SIZE;
memcpy((char *)bptr, d, ETH_ALEN);
bptr += ETH_ALEN;
memcpy((char *)bptr, nic->node_addr, ETH_ALEN);
bptr += ETH_ALEN;
memcpy((char *)bptr, (char *)&type, sizeof(type));
bptr += sizeof(type);
memcpy((char *)bptr, p, s);
/* Change the offset in the IDLELOOP */
*(unsigned short *)(mem_start + IDLELOOP + 4) = TX_BUF_START;
#endif
#ifdef ETHERBOOT16
memcpyf(bptr, (char *)tx_cmd, sizeof(tx_cmd));
bptr += sizeof(tx_cmd);
memcpyf(bptr, d, ETHER_ADDR_SIZE);
bptr += ETHER_ADDR_SIZE;
memcpyf(bptr, nic->node_addr, ETHER_ADDR_SIZE);
bptr += ETHER_ADDR_SIZE;
memcpyf(bptr, (char *)&type, sizeof(type));
bptr += sizeof(type);
memcpyf(bptr, p, s);
/* Change the offset in the IDLELOOP */
z = TX_BUF_START;
memcpyf(mem_start + IDLELOOP + 4, (char *)&z, sizeof(z));
#endif
/* Wait for transmit completion */
while (
#ifdef ETHERBOOT16
read_mem(mem_start + TX_BUF_START, shmem),
#endif
(shmem[0] & 0x2000) == 0)
;
/* Change the offset in the IDLELOOP back and
change the final loop to point here */
#ifdef ETHERBOOT32
*(unsigned short *)(mem_start + IDLELOOP + 4) = IDLELOOP;
*(unsigned short *)(mem_start + TX_BUF_START + 20) = IDLELOOP;
#endif
#ifdef ETHERBOOT16
z = IDLELOOP;
memcpyf(mem_start + IDLELOOP + 4, (char *)&z, sizeof(z));
memcpyf(mem_start + TX_BUF_START + 20, (char *)&z, sizeof(z));
#endif
ack_status();
}
@ -567,22 +480,11 @@ static void i82586_transmit(
***************************************************************************/
static void i82586_disable(struct nic *nic)
{
#ifdef ETHERBOOT32
unsigned short *shmem = (short *)mem_start;
#endif
#ifdef ETHERBOOT16
unsigned short shmem[CONFIG_CMD>>1];
#endif
#if 0
/* Flush the Tx and disable Rx. */
#ifdef ETHERBOOT16
read_mem(mem_start, shmem);
#endif
shmem[iSCB_CMD>>1] = RX_SUSPEND | CUC_SUSPEND;
#ifdef ETHERBOOT16
memcpyf(mem_start, shmem, sizeof(shmem));
#endif
outb(0, ioaddr + I82586_ATTN);
#ifdef INCLUDE_NI5210
outb(0, ioaddr + NI52_RESET);
@ -618,17 +520,14 @@ static int t507_probe1(struct nic *nic, unsigned short ioaddr)
mem_end = mem_start + size;
scb_base = 65536L - size;
if_port = inb(ioaddr + ROM_CONFIG) & 0x80;
printf("\n3c507 ioaddr 0x%x, IRQ %d, mem [0x%X-0x%X], %sternal xcvr, addr ",
ioaddr, irq, mem_start, mem_end, if_port ? "in" : "ex");
/* Get station address */
outb(0x01, ioaddr + MISC_CTRL);
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
for (i = 0; i < ETH_ALEN; ++i)
{
printf("%b", nic->node_addr[i] = inb(ioaddr+i));
if (i < ETHER_ADDR_SIZE -1)
printf(":");
nic->node_addr[i] = inb(ioaddr+i);
}
putchar('\n');
printf("\n3c507 ioaddr %#hX, IRQ %d, mem [%#X-%#X], %sternal xcvr, addr %!\n",
ioaddr, irq, mem_start, mem_end, if_port ? "in" : "ex", nic->node_addr);
return (1);
}
@ -695,46 +594,28 @@ static int ni5210_probe2(void)
/* Write the words at 0xfff6. */
/* Write the words at 0x0000. */
#ifdef ETHERBOOT32
memcpy((char *)(mem_end - 10), (char *)init_words, 10);
memcpy((char *)mem_start, (char *)&init_words[5], sizeof(init_words) - 10);
if (*(unsigned short *)mem_start != 1)
return (0);
#endif
#ifdef ETHERBOOT16
memcpyf(mem_end - 10, (char *)init_words, 10);
memcpyf(mem_start, (char *)&init_words[5], sizeof(init_words) - 10);
fmemcpy((char *)&i, mem_start, sizeof(unsigned short));
if (i != 1)
return (0);
#endif
outb(0, ioaddr + NI52_RESET);
outb(0, ioaddr + I82586_ATTN);
udelay(32);
i = 50;
while (
#ifdef ETHERBOOT16
read_mem(mem_start, shmem),
#endif
shmem[iSCB_STATUS>>1] == 0)
{
if (--i == 0)
{
printf("i82586 initialisation timed out with status %x, cmd %x\n",
printf("i82586 initialisation timed out with status %hX, cmd %hX\n",
shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
break;
}
}
/* Issue channel-attn -- the 82586 won't start. */
outb(0, ioaddr + I82586_ATTN);
#ifdef ETHERBOOT32
if (*(unsigned short *)mem_start != 0)
return (0);
#endif
#ifdef ETHERBOOT16
fmemcpy((char *)&i, mem_start, sizeof(unsigned short));
if (i != 0)
return (0);
#endif
return (1);
}
@ -756,16 +637,13 @@ static int ni5210_probe1(struct nic *nic)
break;
if (mem_start == 0)
return (0);
printf("\nNI5210 ioaddr 0x%x, mem [0x%X-0x%X], addr ",
ioaddr, mem_start, mem_end);
/* Get station address */
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
for (i = 0; i < ETH_ALEN; ++i)
{
printf("%b", nic->node_addr[i] = inb(ioaddr+i));
if (i < ETHER_ADDR_SIZE -1)
printf(":");
nic->node_addr[i] = inb(ioaddr+i);
}
putchar('\n');
printf("\nNI5210 ioaddr %#hX, mem [%#X-%#X], addr %!\n",
ioaddr, mem_start, mem_end, nic->node_addr);
return (1);
}
@ -865,46 +743,27 @@ static int exos205_probe2(void)
/* Write the words at 0xfff6. */
/* Write the words at 0x0000. */
#ifdef ETHERBOOT32
memcpy((char *)(mem_end - 10), (char *)init_words, 10);
memcpy((char *)mem_start, (char *)&init_words[5], sizeof(init_words) - 10);
if (*(unsigned short *)mem_start != 1)
return (0);
#endif
#ifdef ETHERBOOT16
memcpyf(mem_end - 10, (char *)init_words, 10);
memcpyf(mem_start, (char *)&init_words[5], sizeof(init_words) - 10);
fmemcpy((char *)&i, mem_start, sizeof(unsigned short));
if (i != 1)
return (0);
#endif
outb(0, ioaddr + EXOS205_RESET);
outb(0, ioaddr + I82586_ATTN);
i = 50;
while (
#ifdef ETHERBOOT16
read_mem(mem_start, shmem),
#endif
shmem[iSCB_STATUS>>1] == 0)
{
if (--i == 0)
{
printf("i82586 initialisation timed out with status %x, cmd %x\n",
printf("i82586 initialisation timed out with status %hX, cmd %hX\n",
shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]);
break;
}
}
/* Issue channel-attn -- the 82586 won't start. */
outb(0, ioaddr + I82586_ATTN);
#ifdef ETHERBOOT32
if (*(unsigned short *)mem_start != 0)
return (0);
#endif
#ifdef ETHERBOOT16
fmemcpy((char *)&i, mem_start, sizeof(unsigned short));
if (i != 0)
return (0);
#endif
return (1);
}
@ -922,16 +781,13 @@ static int exos205_probe1(struct nic *nic)
break;
if (mem_start == 0)
return (0);
printf("\nEXOS205 ioaddr 0x%x, mem [0x%X-0x%X], addr ",
ioaddr, mem_start, mem_end);
/* Get station address */
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
for (i = 0; i < ETH_ALEN; ++i)
{
printf("%b", nic->node_addr[i] = inb(ioaddr+i));
if (i < ETHER_ADDR_SIZE -1)
printf(":");
nic->node_addr[i] = inb(ioaddr+i);
}
putchar('\n');
printf("\nEXOS205 ioaddr %#hX, mem [%#X-%#X], addr %!\n",
ioaddr, mem_start, mem_end, nic->node_addr);
return (1);
}

View file

@ -39,10 +39,21 @@ Ken Yap, July 1997
#define LANCE_TOTAL_SIZE 0x10
#endif
/* lance_poll() now can use multiple Rx buffers to prevent packet loss. Set
* Set LANCE_LOG_RX_BUFFERS to 0..7 for 1, 2, 4, 8, 16, 32, 64 or 128 Rx
* buffers. Usually 4 (=16 Rx buffers) is a good value. (Andreas Neuhaus)
* Decreased to 2 (=4 Rx buffers) (Ken Yap, 20010305) */
#define LANCE_LOG_RX_BUFFERS 2 /* Use 2^2=4 Rx buffers */
#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
struct lance_init_block
{
unsigned short mode;
unsigned char phys_addr[6];
unsigned char phys_addr[ETH_ALEN];
unsigned long filter[2];
Address rx_ring;
Address tx_ring;
@ -52,7 +63,7 @@ struct lance_rx_head
{
union {
Address base;
char addr[4];
unsigned char addr[4];
} u;
short buf_length; /* 2s complement */
short msg_length;
@ -62,7 +73,7 @@ struct lance_tx_head
{
union {
Address base;
char addr[4];
unsigned char addr[4];
} u;
short buf_length; /* 2s complement */
short misc;
@ -71,20 +82,26 @@ struct lance_tx_head
struct lance_interface
{
struct lance_init_block init_block;
struct lance_rx_head rx_ring;
struct lance_rx_head rx_ring[RX_RING_SIZE];
struct lance_tx_head tx_ring;
unsigned char rbuf[ETH_MAX_PACKET];
unsigned char tbuf[ETH_MAX_PACKET];
unsigned char rbuf[RX_RING_SIZE][ETH_FRAME_LEN+4];
unsigned char tbuf[ETH_FRAME_LEN];
/*
* Do not alter the order of the struct members above;
* the hardware depends on the correct alignment.
*/
int rx_idx;
};
#define LANCE_MUST_PAD 0x00000001
#define LANCE_ENABLE_AUTOSELECT 0x00000002
#define LANCE_SELECT_PHONELINE 0x00000004
#define LANCE_MUST_UNRESET 0x00000008
/* A mapping from the chip ID number to the part number and features.
These are from the datasheets -- in real life the '970 version
reportedly has the same ID as the '965. */
static struct lance_chip_type
static const struct lance_chip_type
{
int id_number;
const char *name;
@ -104,32 +121,33 @@ static struct lance_chip_type
LANCE_ENABLE_AUTOSELECT},
{0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
LANCE_ENABLE_AUTOSELECT},
{0x2625, "PCnet-FAST III 79C973", /* 79C973 PCInet-FAST III. */
LANCE_ENABLE_AUTOSELECT},
{0x2626, "PCnet/HomePNA 79C978",
LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE},
{0x0, "PCnet (unknown)",
LANCE_ENABLE_AUTOSELECT},
};
/* Define a macro for converting program addresses to real addresses */
#ifdef ETHERBOOT32
#undef virt_to_bus
#define virt_to_bus(x) ((unsigned long)x)
#endif
#ifdef ETHERBOOT16
#define virt_to_bus(x) (((Address)x)+RELOC)
#endif /* ETHERBOOT16 */
static int chip_version;
static int lance_version;
static unsigned short ioaddr;
#ifndef INCLUDE_LANCE
static int dma;
#endif
static struct lance_interface *lp;
/* additional 8 bytes for 8-byte alignment space */
#ifndef USE_INTERNAL_BUFFER
#ifdef USE_LOWMEM_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 */
@ -199,9 +217,9 @@ static void lance_reset(struct nic *nic)
/* Reset the LANCE */
(void)inw(ioaddr+LANCE_RESET);
/* Un-Reset the LANCE, needed only for the NE2100 */
if (chip_table[chip_version].flags & LANCE_MUST_UNRESET)
if (chip_table[lance_version].flags & LANCE_MUST_UNRESET)
outw(0, ioaddr+LANCE_RESET);
if (chip_table[chip_version].flags & LANCE_ENABLE_AUTOSELECT)
if (chip_table[lance_version].flags & LANCE_ENABLE_AUTOSELECT)
{
/* This is 79C960 specific; Turn on auto-select of media
(AUI, BNC). */
@ -209,16 +227,48 @@ static void lance_reset(struct nic *nic)
/* Don't touch 10base2 power bit. */
outw(inw(ioaddr+LANCE_BUS_IF) | 0x2, ioaddr+LANCE_BUS_IF);
}
/* HomePNA cards need to explicitly pick the phoneline interface.
* Some of these cards have ethernet interfaces as well, this
* code might require some modification for those.
*/
if (chip_table[lance_version].flags & LANCE_SELECT_PHONELINE) {
short media, check ;
/* this is specific to HomePNA cards... */
outw(49, ioaddr+0x12) ;
media = inw(ioaddr+0x16) ;
#ifdef DEBUG
printf("media was %d\n", media) ;
#endif
media &= ~3 ;
media |= 1 ;
#ifdef DEBUG
printf("media changed to %d\n", media) ;
#endif
media &= ~3 ;
media |= 1 ;
outw(49, ioaddr+0x12) ;
outw(media, ioaddr+0x16) ;
outw(49, ioaddr+0x12) ;
check = inw(ioaddr+0x16) ;
#ifdef DEBUG
printf("check %s, media was set properly\n",
check == media ? "passed" : "FAILED" ) ;
#endif
}
/* Re-initialise the LANCE, and start it when done. */
/* Set station address */
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
for (i = 0; i < ETH_ALEN; ++i)
lp->init_block.phys_addr[i] = nic->node_addr[i];
/* Preset the receive ring header */
lp->rx_ring.buf_length = -ETH_MAX_PACKET;
/* OWN */
lp->rx_ring.u.base = virt_to_bus(lp->rbuf) & 0xffffff;
/* we set the top byte as the very last thing */
lp->rx_ring.u.addr[3] = 0x80;
/* Preset the receive ring headers */
for (i=0; i<RX_RING_SIZE; i++) {
lp->rx_ring[i].buf_length = -ETH_FRAME_LEN-4;
/* OWN */
lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;
/* we set the top byte as the very last thing */
lp->rx_ring[i].u.addr[3] = 0x80;
}
lp->rx_idx = 0;
lp->init_block.mode = 0x0; /* enable Rx and Tx */
l = (Address)virt_to_bus(&lp->init_block);
outw(0x1, ioaddr+LANCE_ADDR);
@ -234,9 +284,13 @@ static void lance_reset(struct nic *nic)
(void)inw(ioaddr+LANCE_ADDR);
outw(0x4, ioaddr+LANCE_DATA); /* stop */
outw(0x1, ioaddr+LANCE_DATA); /* init */
for (i = 100; i > 0; --i)
for (i = 10000; i > 0; --i)
if (inw(ioaddr+LANCE_DATA) & 0x100)
break;
#ifdef DEBUG
if (i <= 0)
printf("Init timed out\n");
#endif
/* Apparently clearing the InitDone bit here triggers a bug
in the '974. (Mark Stockton) */
outw(0x2, ioaddr+LANCE_DATA); /* start */
@ -249,23 +303,29 @@ static int lance_poll(struct nic *nic)
{
int status;
status = lp->rx_ring.u.base >> 24;
status = lp->rx_ring[lp->rx_idx].u.base >> 24;
if (status & 0x80)
return (0);
#ifdef DEBUG
printf("LANCE packet received rx_ring.u.base %X mcnt %x csr0 %x\n",
lp->rx_ring.u.base, lp->rx_ring.msg_length,
printf("LANCE packet received rx_ring.u.base %X mcnt %hX csr0 %hX\n",
lp->rx_ring[lp->rx_idx].u.base, lp->rx_ring[lp->rx_idx].msg_length,
inw(ioaddr+LANCE_DATA));
#endif
if (status == 0x3)
memcpy(nic->packet, lp->rbuf, nic->packetlen = lp->rx_ring.msg_length);
memcpy(nic->packet, lp->rbuf[lp->rx_idx], nic->packetlen = lp->rx_ring[lp->rx_idx].msg_length);
/* Andrew Boyd of QNX reports that some revs of the 79C765
clear the buffer length */
lp->rx_ring.buf_length = -ETH_MAX_PACKET;
lp->rx_ring.u.addr[3] |= 0x80; /* prime for next receive */
lp->rx_ring[lp->rx_idx].buf_length = -ETH_FRAME_LEN-4;
lp->rx_ring[lp->rx_idx].u.addr[3] |= 0x80; /* prime for next receive */
/* I'm not sure if the following is still ok with multiple Rx buffers, but it works */
outw(0x0, ioaddr+LANCE_ADDR);
(void)inw(ioaddr+LANCE_ADDR);
outw(0x500, ioaddr+LANCE_DATA); /* clear receive + InitDone */
/* Switch to the next Rx ring buffer */
lp->rx_idx = (lp->rx_idx + 1) & RX_RING_MOD_MASK;
return (status == 0x3);
}
@ -282,14 +342,14 @@ static void lance_transmit(
unsigned long time;
/* copy the packet to ring buffer */
memcpy(lp->tbuf, d, ETHER_ADDR_SIZE); /* dst */
memcpy(&lp->tbuf[ETHER_ADDR_SIZE], nic->node_addr, ETHER_ADDR_SIZE); /* src */
lp->tbuf[ETHER_ADDR_SIZE+ETHER_ADDR_SIZE] = t >> 8; /* type */
lp->tbuf[ETHER_ADDR_SIZE+ETHER_ADDR_SIZE+1] = t; /* type */
memcpy(&lp->tbuf[ETHER_HDR_SIZE], p, s);
s += ETHER_HDR_SIZE;
memcpy(lp->tbuf, d, ETH_ALEN); /* dst */
memcpy(&lp->tbuf[ETH_ALEN], nic->node_addr, ETH_ALEN); /* src */
lp->tbuf[ETH_ALEN+ETH_ALEN] = t >> 8; /* type */
lp->tbuf[ETH_ALEN+ETH_ALEN+1] = t; /* type */
memcpy(&lp->tbuf[ETH_HLEN], p, s);
s += ETH_HLEN;
if (chip_table[chip_version].flags & LANCE_MUST_PAD)
while (s < ETH_MIN_PACKET) /* pad to min length */
while (s < ETH_ZLEN) /* pad to min length */
lp->tbuf[s++] = 0;
lp->tx_ring.buf_length = -s;
lp->tx_ring.misc = 0x0;
@ -299,7 +359,12 @@ static void lance_transmit(
lp->tx_ring.u.addr[3] = 0x83;
/* Trigger an immediate send poll */
outw(0x0, ioaddr+LANCE_ADDR);
outw(0x48, ioaddr+LANCE_DATA);
(void)inw(ioaddr+LANCE_ADDR); /* as in the datasheets... */
/* Klaus Espenlaub: the value below was 0x48, but that enabled the
* interrupt line, causing a hang if for some reasone the interrupt
* controller had the LANCE interrupt enabled. I have no idea why
* nobody ran into this before... */
outw(0x08, ioaddr+LANCE_DATA);
/* wait for transmit complete */
time = currticks() + TICKS_PER_SEC; /* wait one second */
while (currticks() < time && (lp->tx_ring.u.base & 0x80000000) != 0)
@ -309,7 +374,7 @@ static void lance_transmit(
(void)inw(ioaddr+LANCE_ADDR);
outw(0x200, ioaddr+LANCE_DATA); /* clear transmit + InitDone */
#ifdef DEBUG
printf("tx_ring.u.base %X tx_ring.buf_length %x tx_ring.misc %x csr0 %x\n",
printf("tx_ring.u.base %X tx_ring.buf_length %hX tx_ring.misc %hX csr0 %hX\n",
lp->tx_ring.u.base, lp->tx_ring.buf_length, lp->tx_ring.misc,
inw(ioaddr+LANCE_DATA));
#endif
@ -317,6 +382,13 @@ static void lance_transmit(
static void lance_disable(struct nic *nic)
{
(void)inw(ioaddr+LANCE_RESET);
if (chip_table[lance_version].flags & LANCE_MUST_UNRESET)
outw(0, ioaddr+LANCE_RESET);
outw(0, ioaddr+LANCE_ADDR);
outw(0x0004, ioaddr+LANCE_DATA); /* stop the LANCE */
#ifndef INCLUDE_LANCE
disable_dma(dma);
#endif
@ -328,11 +400,13 @@ static int lance_probe1(struct nic *nic, struct pci_device *pci)
static int lance_probe1(struct nic *nic)
#endif
{
int reset_val, lance_version;
int reset_val ;
unsigned int i;
Address l;
short dma_channels;
#ifndef INCLUDE_LANCE
static const char dmas[] = { 5, 6, 7, 3 };
#endif
reset_val = inw(ioaddr+LANCE_RESET);
outw(reset_val, ioaddr+LANCE_RESET);
@ -361,8 +435,8 @@ static int lance_probe1(struct nic *nic)
lp = (struct lance_interface *)l;
lp->init_block.mode = 0x3; /* disable Rx and Tx */
lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
/* top bits are zero, we have only one buffer each for Rx and Tx */
lp->init_block.rx_ring = virt_to_bus(&lp->rx_ring) & 0xffffff;
/* using multiple Rx buffer and a single Tx buffer */
lp->init_block.rx_ring = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
lp->init_block.tx_ring = virt_to_bus(&lp->tx_ring) & 0xffffff;
l = virt_to_bus(&lp->init_block);
outw(0x1, ioaddr+LANCE_ADDR);
@ -376,6 +450,10 @@ static int lance_probe1(struct nic *nic)
outw(0x915, ioaddr+LANCE_DATA);
outw(0x0, ioaddr+LANCE_ADDR);
(void)inw(ioaddr+LANCE_ADDR);
/* Get station address */
for (i = 0; i < ETH_ALEN; ++i) {
nic->node_addr[i] = inb(ioaddr+LANCE_ETH_ADDR+i);
}
#ifndef INCLUDE_LANCE
/* now probe for DMA channel */
dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0xf) |
@ -404,19 +482,11 @@ static int lance_probe1(struct nic *nic)
}
if (i >= (sizeof(dmas)/sizeof(dmas[0])))
dma = 0;
printf("\n%s base 0x%x, DMA %d, addr ",
chip_table[lance_version].name, ioaddr, dma);
printf("\n%s base %#X, DMA %d, addr %!\n",
chip_table[lance_version].name, ioaddr, dma, nic->node_addr);
#else
printf(" %s base 0x%x, addr ", chip_table[lance_version].name, ioaddr);
printf(" %s base %#hX, addr %!\n", chip_table[lance_version].name, ioaddr, nic->node_addr);
#endif
/* Get station address */
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
{
printf("%b", nic->node_addr[i] = inb(ioaddr+LANCE_ETH_ADDR+i));
if (i < ETHER_ADDR_SIZE -1)
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. */
@ -442,15 +512,22 @@ struct nic *ni6510_probe(struct nic *nic, unsigned short *probe_addrs)
#endif
{
unsigned short *p;
#ifndef INCLUDE_LANCE
static unsigned short io_addrs[] = { 0x300, 0x320, 0x340, 0x360, 0 };
#endif
/* if probe_addrs is 0, then routine can use a hardwired default */
if (probe_addrs == 0)
if (probe_addrs == 0) {
#ifdef INCLUDE_LANCE
return 0;
#else
probe_addrs = io_addrs;
#endif
}
for (p = probe_addrs; (ioaddr = *p) != 0; ++p)
{
char offset15, offset14 = inb(ioaddr + 14);
short pci_cmd;
unsigned short pci_cmd;
#ifdef INCLUDE_NE2100
if ((offset14 == 0x52 || offset14 == 0x57) &&
@ -465,11 +542,7 @@ struct nic *ni6510_probe(struct nic *nic, unsigned short *probe_addrs)
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);
}
adjust_pci_device(pci);
if (lance_probe1(nic, pci) >= 0)
break;
#endif
@ -485,8 +558,7 @@ struct nic *ni6510_probe(struct nic *nic, unsigned short *probe_addrs)
nic->disable = lance_disable;
return nic;
}
/* else */
{
return 0;
}
/* no board found */
return 0;
}

View file

@ -251,4 +251,41 @@ __asm__ __volatile__("cld\n\t" \
__constant_c_x_memset((s),(c),(count)) : \
__memset((s),(c),(count)))
#define __HAVE_ARCH_STRNCMP
static inline int strncmp(const char * cs,const char * ct,size_t count)
{
register int __res;
int d0, d1, d2;
__asm__ __volatile__(
"1:\tdecl %3\n\t"
"js 2f\n\t"
"lodsb\n\t"
"scasb\n\t"
"jne 3f\n\t"
"testb %%al,%%al\n\t"
"jne 1b\n"
"2:\txorl %%eax,%%eax\n\t"
"jmp 4f\n"
"3:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"4:"
:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
:"1" (cs),"2" (ct),"3" (count));
return __res;
}
#define __HAVE_ARCH_STRLEN
static inline size_t strlen(const char * s)
{
int d0;
register int __res;
__asm__ __volatile__(
"repne\n\t"
"scasb\n\t"
"notl %0\n\t"
"decl %0"
:"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
return __res;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000 Free Software Foundation, Inc.
* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -17,324 +17,237 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* Based on "src/misc.c" in etherboot-4.5.8. */
/* Based on "src/misc.c" in etherboot-5.0.5. */
/**************************************************************************
MISC Support Routines
**************************************************************************/
#define GRUB 1
#include <etherboot.h>
#include "etherboot.h"
/**************************************************************************
SLEEP
**************************************************************************/
void sleep(int secs)
void
sleep (int secs)
{
unsigned long tmo;
unsigned long tmo = currticks () + secs;
for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; )
/* Nothing */;
while (currticks () < tmo)
;
}
/**************************************************************************
TWIDDLE
**************************************************************************/
void twiddle()
void
twiddle (void)
{
static unsigned long lastticks = 0;
static int count=0;
static char tiddles[]="-\\|/";
unsigned long ticks;
if ((ticks = currticks()) == lastticks)
return;
lastticks = ticks;
putchar(tiddles[(count++)&3]);
putchar('\b');
}
#ifndef GRUB
/**************************************************************************
STRCASECMP (not entirely correct, but this will do for our purposes)
**************************************************************************/
int strcasecmp(a,b)
char *a, *b;
{
while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
return((*a & ~0x20) - (*b & ~0x20));
grub_putchar('.');
}
/* Because Etherboot uses its own formats for the printf family,
define separate definitions from GRUB. */
/**************************************************************************
PRINTF and friends
Formats:
%X - 4 byte ASCII (8 hex digits)
%x - 2 byte ASCII (4 hex digits)
%b - 1 byte ASCII (2 hex digits)
%d - decimal (also %i)
%c - ASCII char
%s - ASCII string
%I - Internet address in x.x.x.x notation
%[#]x - 4 bytes long (8 hex digits, lower case)
%[#]X - 4 bytes long (8 hex digits, upper case)
%[#]hx - 2 bytes int (4 hex digits, lower case)
%[#]hX - 2 bytes int (4 hex digits, upper case)
%[#]hhx - 1 byte int (2 hex digits, lower case)
%[#]hhX - 1 byte int (2 hex digits, upper case)
- optional # prefixes 0x or 0X
%d - decimal int
%c - char
%s - string
%@ - Internet address in ddd.ddd.ddd.ddd notation
%! - Ethernet address in xx:xx:xx:xx:xx:xx notation
Note: width specification not supported
**************************************************************************/
static char hex[]="0123456789ABCDEF";
static char *do_printf(char *buf, const char *fmt, const int *dp)
static int
etherboot_vsprintf (char *buf, const char *fmt, const int *dp)
{
register char *p;
char tmp[16];
while (*fmt) {
if (*fmt == '%') { /* switch() uses more space */
fmt++;
if (*fmt == 'X') {
const long *lp = (const long *)dp;
register long h = *lp++;
dp = (const int *)lp;
*(buf++) = hex[(h>>28)& 0x0F];
*(buf++) = hex[(h>>24)& 0x0F];
*(buf++) = hex[(h>>20)& 0x0F];
*(buf++) = hex[(h>>16)& 0x0F];
*(buf++) = hex[(h>>12)& 0x0F];
*(buf++) = hex[(h>>8)& 0x0F];
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'x') {
register int h = *(dp++);
*(buf++) = hex[(h>>12)& 0x0F];
*(buf++) = hex[(h>>8)& 0x0F];
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'b') {
register int h = *(dp++);
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if ((*fmt == 'd') || (*fmt == 'i')) {
register int dec = *(dp++);
p = tmp;
if (dec < 0) {
*(buf++) = '-';
dec = -dec;
}
do {
*(p++) = '0' + (dec%10);
dec = dec/10;
} while(dec);
while ((--p) >= tmp) *(buf++) = *p;
}
if (*fmt == 'I') {
union {
long l;
unsigned char c[4];
} u;
const long *lp = (const long *)dp;
u.l = *lp++;
dp = (const int *)lp;
buf = sprintf(buf,"%d.%d.%d.%d",
u.c[0], u.c[1], u.c[2], u.c[3]);
}
if (*fmt == 'c')
*(buf++) = *(dp++);
if (*fmt == 's') {
p = (char *)*dp++;
while (*p) *(buf++) = *p++;
}
} else *(buf++) = *fmt;
fmt++;
char *p, *s;
s = buf;
for ( ; *fmt != '\0'; ++fmt)
{
if (*fmt != '%')
{
buf ? *s++ = *fmt : grub_putchar (*fmt);
continue;
}
*buf = 0;
return(buf);
}
char *sprintf(char *buf, const char *fmt, ...)
{
return do_printf(buf, fmt, ((const int *)&fmt)+1);
}
void printf(const char *fmt, ...)
{
char buf[120],*p;
p = buf;
do_printf(buf, fmt, ((const int *)&fmt)+1);
while (*p) putchar(*p++);
}
#endif /* ! GRUB */
#if defined(IMAGE_MENU) || defined(GRUB)
/**************************************************************************
INET_ATON - Convert an ascii x.x.x.x to binary form
**************************************************************************/
int inet_aton(char *p, in_addr *i)
{
unsigned long ip = 0;
int val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = (ip << 8) | val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = (ip << 8) | val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
i->s_addr = htonl((ip << 8) | val);
return(1);
}
#endif /* IMAGE_MENU || GRUB */
int getdec(char **ptr)
{
char *p = *ptr;
int ret=0;
if ((*p < '0') || (*p > '9')) return(-1);
while ((*p >= '0') && (*p <= '9')) {
ret = ret*10 + (*p - '0');
p++;
if (*++fmt == 's')
{
for (p = (char *) *dp++; *p != '\0'; p++)
buf ? *s++ = *p : grub_putchar (*p);
}
*ptr = p;
return(ret);
else
{
/* Length of item is bounded */
char tmp[20], *q = tmp;
int alt = 0;
int shift = 28;
if (*fmt == '#')
{
alt = 1;
fmt++;
}
if (*fmt == 'h')
{
shift = 12;
fmt++;
}
if (*fmt == 'h')
{
shift = 4;
fmt++;
}
/*
* Before each format q points to tmp buffer
* After each format q points past end of item
*/
if ((*fmt | 0x20) == 'x')
{
/* With x86 gcc, sizeof(long) == sizeof(int) */
const long *lp = (const long *) dp;
long h = *lp++;
int ncase = (*fmt & 0x20);
dp = (const int *) lp;
if (alt)
{
*q++ = '0';
*q++ = 'X' | ncase;
}
for (; shift >= 0; shift -= 4)
*q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
}
else if (*fmt == 'd')
{
int i = *dp++;
char *r;
if (i < 0)
{
*q++ = '-';
i = -i;
}
p = q; /* save beginning of digits */
do
{
*q++ = '0' + (i % 10);
i /= 10;
}
while (i);
/* reverse digits, stop in middle */
r = q; /* don't alter q */
while (--r > p)
{
i = *r;
*r = *p;
*p++ = i;
}
}
else if (*fmt == '@')
{
unsigned char *r;
union
{
long l;
unsigned char c[4];
}
u;
const long *lp = (const long *) dp;
u.l = *lp++;
dp = (const int *) lp;
for (r = &u.c[0]; r < &u.c[4]; ++r)
q += etherboot_sprintf (q, "%d.", *r);
--q;
}
else if (*fmt == '!')
{
char *r;
p = (char *) *dp++;
for (r = p + ETH_ALEN; p < r; ++p)
q += etherboot_sprintf (q, "%hhX:", *p);
--q;
}
else if (*fmt == 'c')
*q++ = *dp++;
else
*q++ = *fmt;
/* now output the saved string */
for (p = tmp; p < q; ++p)
buf ? *s++ = *p : grub_putchar (*p);
}
}
if (buf)
*s = '\0';
return (s - buf);
}
#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 KC_CMD_WIN 0xd0 /* read output port */
#define KC_CMD_WOUT 0xd1 /* write output port */
#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)
int
etherboot_sprintf (char *buf, const char *fmt, ...)
{
unsigned long time;
char st;
slowdownio();
time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */
while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
(st & K_IBUF_FUL)) &&
currticks() < time)
inb(K_RDWR);
}
#endif IBM_L40
/*
* Gate A20 for high memory
*/
void gateA20_set(void)
{
#ifdef IBM_L40
outb(0x2, 0x92);
#else /* IBM_L40 */
empty_8042();
outb(KC_CMD_WOUT, K_CMD);
empty_8042();
outb(KB_SET_A20, K_RDWR);
empty_8042();
#endif /* IBM_L40 */
return etherboot_vsprintf (buf, fmt, ((const int *) &fmt) + 1);
}
#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)
etherboot_printf (const char *fmt, ...)
{
#ifndef ANSIESC
if (c == '\n')
putchar('\r');
#endif
#ifdef CONSOLE_CRT
#ifdef ANSIESC
handleansi(c);
#else
putc(c);
#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(void)
{
int c = 256;
do {
#ifdef CONSOLE_CRT
if (ischar())
c = getc();
#endif
#ifdef CONSOLE_SERIAL
if (serial_ischar())
c = serial_getc();
#endif
} while (c==256);
if (c == '\r')
c = '\n';
return c;
(void) etherboot_vsprintf (0, fmt, ((const int *) &fmt) + 1);
}
int
iskey(void)
inet_aton (char *p, in_addr *addr)
{
#ifdef CONSOLE_CRT
if (ischar())
return 1;
#endif
#ifdef CONSOLE_SERIAL
if (serial_ischar())
return 1;
#endif
unsigned long ip = 0;
int val;
int i;
for (i = 0; i < 4; i++)
{
val = getdec (&p);
if (val < 0 || val > 255)
return 0;
}
#endif /* ETHERBOOT32 */
#endif /* ! GRUB */
if (*p++ != '.')
return 0;
ip = (ip << 8) | val;
}
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
addr->s_addr = htonl (ip);
return 1;
}
int
getdec (char **ptr)
{
char *p = *ptr;
int ret = 0;
if (*p < '0' || *p > '9')
return -1;
while (*p >= '0' && *p <= '9')
{
ret = ret * 10 + (*p - '0');
p++;
}
*ptr = p;
return ret;
}

371
netboot/ni5010.c Normal file
View file

@ -0,0 +1,371 @@
/**************************************************************************
Etherboot - BOOTP/TFTP Bootstrap Program
Driver for NI5010.
Code freely taken from Jan-Pascal van Best and Andreas Mohr's
Linux NI5010 driver.
***************************************************************************/
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* 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"
/* to get our own prototype */
#include "cards.h"
/* ni5010.h file included verbatim */
/*
* Racal-Interlan ni5010 Ethernet definitions
*
* This is an extension to the Linux operating system, and is covered by the
* same Gnu Public License that covers that work.
*
* copyrights (c) 1996 by Jan-Pascal van Best (jvbest@wi.leidenuniv.nl)
*
* I have done a look in the following sources:
* crynwr-packet-driver by Russ Nelson
*/
#define NI5010_BUFSIZE 2048 /* number of bytes in a buffer */
#define NI5010_MAGICVAL0 0x00 /* magic-values for ni5010 card */
#define NI5010_MAGICVAL1 0x55
#define NI5010_MAGICVAL2 0xAA
#define SA_ADDR0 0x02
#define SA_ADDR1 0x07
#define SA_ADDR2 0x01
/* The number of low I/O ports used by the ni5010 ethercard. */
#define NI5010_IO_EXTENT 32
#define PRINTK(x) if (NI5010_DEBUG) printk x
#define PRINTK2(x) if (NI5010_DEBUG>=2) printk x
#define PRINTK3(x) if (NI5010_DEBUG>=3) printk x
/* The various IE command registers */
#define EDLC_XSTAT (ioaddr + 0x00) /* EDLC transmit csr */
#define EDLC_XCLR (ioaddr + 0x00) /* EDLC transmit "Clear IRQ" */
#define EDLC_XMASK (ioaddr + 0x01) /* EDLC transmit "IRQ Masks" */
#define EDLC_RSTAT (ioaddr + 0x02) /* EDLC receive csr */
#define EDLC_RCLR (ioaddr + 0x02) /* EDLC receive "Clear IRQ" */
#define EDLC_RMASK (ioaddr + 0x03) /* EDLC receive "IRQ Masks" */
#define EDLC_XMODE (ioaddr + 0x04) /* EDLC transmit Mode */
#define EDLC_RMODE (ioaddr + 0x05) /* EDLC receive Mode */
#define EDLC_RESET (ioaddr + 0x06) /* EDLC RESET register */
#define EDLC_TDR1 (ioaddr + 0x07) /* "Time Domain Reflectometry" reg1 */
#define EDLC_ADDR (ioaddr + 0x08) /* EDLC station address, 6 bytes */
/* 0x0E doesn't exist for r/w */
#define EDLC_TDR2 (ioaddr + 0x0f) /* "Time Domain Reflectometry" reg2 */
#define IE_GP (ioaddr + 0x10) /* GP pointer (word register) */
/* 0x11 is 2nd byte of GP Pointer */
#define IE_RCNT (ioaddr + 0x10) /* Count of bytes in rcv'd packet */
/* 0x11 is 2nd byte of "Byte Count" */
#define IE_MMODE (ioaddr + 0x12) /* Memory Mode register */
#define IE_DMA_RST (ioaddr + 0x13) /* IE DMA Reset. write only */
#define IE_ISTAT (ioaddr + 0x13) /* IE Interrupt Status. read only */
#define IE_RBUF (ioaddr + 0x14) /* IE Receive Buffer port */
#define IE_XBUF (ioaddr + 0x15) /* IE Transmit Buffer port */
#define IE_SAPROM (ioaddr + 0x16) /* window on station addr prom */
#define IE_RESET (ioaddr + 0x17) /* any write causes Board Reset */
/* bits in EDLC_XSTAT, interrupt clear on write, status when read */
#define XS_TPOK 0x80 /* transmit packet successful */
#define XS_CS 0x40 /* carrier sense */
#define XS_RCVD 0x20 /* transmitted packet received */
#define XS_SHORT 0x10 /* transmission media is shorted */
#define XS_UFLW 0x08 /* underflow. iff failed board */
#define XS_COLL 0x04 /* collision occurred */
#define XS_16COLL 0x02 /* 16th collision occurred */
#define XS_PERR 0x01 /* parity error */
#define XS_CLR_UFLW 0x08 /* clear underflow */
#define XS_CLR_COLL 0x04 /* clear collision */
#define XS_CLR_16COLL 0x02 /* clear 16th collision */
#define XS_CLR_PERR 0x01 /* clear parity error */
/* bits in EDLC_XMASK, mask/enable transmit interrupts. register is r/w */
#define XM_TPOK 0x80 /* =1 to enable Xmt Pkt OK interrupts */
#define XM_RCVD 0x20 /* =1 to enable Xmt Pkt Rcvd ints */
#define XM_UFLW 0x08 /* =1 to enable Xmt Underflow ints */
#define XM_COLL 0x04 /* =1 to enable Xmt Collision ints */
#define XM_COLL16 0x02 /* =1 to enable Xmt 16th Coll ints */
#define XM_PERR 0x01 /* =1 to enable Xmt Parity Error ints */
/* note: always clear this bit */
#define XM_ALL (XM_TPOK | XM_RCVD | XM_UFLW | XM_COLL | XM_COLL16)
/* bits in EDLC_RSTAT, interrupt clear on write, status when read */
#define RS_PKT_OK 0x80 /* received good packet */
#define RS_RST_PKT 0x10 /* RESET packet received */
#define RS_RUNT 0x08 /* Runt Pkt rcvd. Len < 64 Bytes */
#define RS_ALIGN 0x04 /* Alignment error. not 8 bit aligned */
#define RS_CRC_ERR 0x02 /* Bad CRC on rcvd pkt */
#define RS_OFLW 0x01 /* overflow for rcv FIFO */
#define RS_VALID_BITS ( RS_PKT_OK | RS_RST_PKT | RS_RUNT | RS_ALIGN | RS_CRC_ERR | RS_OFLW )
/* all valid RSTAT bits */
#define RS_CLR_PKT_OK 0x80 /* clear rcvd packet interrupt */
#define RS_CLR_RST_PKT 0x10 /* clear RESET packet received */
#define RS_CLR_RUNT 0x08 /* clear Runt Pckt received */
#define RS_CLR_ALIGN 0x04 /* clear Alignment error */
#define RS_CLR_CRC_ERR 0x02 /* clear CRC error */
#define RS_CLR_OFLW 0x01 /* clear rcv FIFO Overflow */
/* bits in EDLC_RMASK, mask/enable receive interrupts. register is r/w */
#define RM_PKT_OK 0x80 /* =1 to enable rcvd good packet ints */
#define RM_RST_PKT 0x10 /* =1 to enable RESET packet ints */
#define RM_RUNT 0x08 /* =1 to enable Runt Pkt rcvd ints */
#define RM_ALIGN 0x04 /* =1 to enable Alignment error ints */
#define RM_CRC_ERR 0x02 /* =1 to enable Bad CRC error ints */
#define RM_OFLW 0x01 /* =1 to enable overflow error ints */
/* bits in EDLC_RMODE, set Receive Packet mode. register is r/w */
#define RMD_TEST 0x80 /* =1 for Chip testing. normally 0 */
#define RMD_ADD_SIZ 0x10 /* =1 5-byte addr match. normally 0 */
#define RMD_EN_RUNT 0x08 /* =1 enable runt rcv. normally 0 */
#define RMD_EN_RST 0x04 /* =1 to rcv RESET pkt. normally 0 */
#define RMD_PROMISC 0x03 /* receive *all* packets. unusual */
#define RMD_MULTICAST 0x02 /* receive multicasts too. unusual */
#define RMD_BROADCAST 0x01 /* receive broadcasts & normal. usual */
#define RMD_NO_PACKETS 0x00 /* don't receive any packets. unusual */
/* bits in EDLC_XMODE, set Transmit Packet mode. register is r/w */
#define XMD_COLL_CNT 0xf0 /* coll's since success. read-only */
#define XMD_IG_PAR 0x08 /* =1 to ignore parity. ALWAYS set */
#define XMD_T_MODE 0x04 /* =1 to power xcvr. ALWAYS set this */
#define XMD_LBC 0x02 /* =1 for loopback. normally set */
#define XMD_DIS_C 0x01 /* =1 disables contention. normally 0 */
/* bits in EDLC_RESET, write only */
#define RS_RESET 0x80 /* =1 to hold EDLC in reset state */
/* bits in IE_MMODE, write only */
#define MM_EN_DMA 0x80 /* =1 begin DMA xfer, Cplt clrs it */
#define MM_EN_RCV 0x40 /* =1 allows Pkt rcv. clr'd by rcv */
#define MM_EN_XMT 0x20 /* =1 begin Xmt pkt. Cplt clrs it */
#define MM_BUS_PAGE 0x18 /* =00 ALWAYS. Used when MUX=1 */
#define MM_NET_PAGE 0x06 /* =00 ALWAYS. Used when MUX=0 */
#define MM_MUX 0x01 /* =1 means Rcv Buff on system bus */
/* =0 means Xmt Buff on system bus */
/* bits in IE_ISTAT, read only */
#define IS_TDIAG 0x80 /* =1 if Diagnostic problem */
#define IS_EN_RCV 0x20 /* =1 until frame is rcv'd cplt */
#define IS_EN_XMT 0x10 /* =1 until frame is xmt'd cplt */
#define IS_EN_DMA 0x08 /* =1 until DMA is cplt or aborted */
#define IS_DMA_INT 0x04 /* =0 iff DMA done interrupt. */
#define IS_R_INT 0x02 /* =0 iff unmasked Rcv interrupt */
#define IS_X_INT 0x01 /* =0 iff unmasked Xmt interrupt */
/* NIC specific static variables go here */
static unsigned short ioaddr = 0;
static unsigned int bufsize_rcv = 0;
#if 0
static void show_registers(void)
{
printf("XSTAT %hhX ", inb(EDLC_XSTAT));
printf("XMASK %hhX ", inb(EDLC_XMASK));
printf("RSTAT %hhX ", inb(EDLC_RSTAT));
printf("RMASK %hhX ", inb(EDLC_RMASK));
printf("RMODE %hhX ", inb(EDLC_RMODE));
printf("XMODE %hhX ", inb(EDLC_XMODE));
printf("ISTAT %hhX\n", inb(IE_ISTAT));
}
#endif
static void reset_receiver(void)
{
outw(0, IE_GP); /* Receive packet at start of buffer */
outb(RS_VALID_BITS, EDLC_RCLR); /* Clear all pending Rcv interrupts */
outb(MM_EN_RCV, IE_MMODE); /* Enable rcv */
}
/**************************************************************************
RESET - Reset adapter
***************************************************************************/
static void ni5010_reset(struct nic *nic)
{
int i;
/* Reset the hardware here. Don't forget to set the station address. */
outb(RS_RESET, EDLC_RESET); /* Hold up EDLC_RESET while configing board */
outb(0, IE_RESET); /* Hardware reset of ni5010 board */
outb(0, EDLC_XMASK); /* Disable all Xmt interrupts */
outb(0, EDLC_RMASK); /* Disable all Rcv interrupt */
outb(0xFF, EDLC_XCLR); /* Clear all pending Xmt interrupts */
outb(0xFF, EDLC_RCLR); /* Clear all pending Rcv interrupts */
outb(XMD_LBC, EDLC_XMODE); /* Only loopback xmits */
/* Set the station address */
for(i = 0; i < ETH_ALEN; i++)
outb(nic->node_addr[i], EDLC_ADDR + i);
outb(XMD_IG_PAR | XMD_T_MODE | XMD_LBC, EDLC_XMODE);
/* Normal packet xmit mode */
outb(RMD_BROADCAST, EDLC_RMODE);
/* Receive broadcast and normal packets */
reset_receiver();
outb(0x00, EDLC_RESET); /* Un-reset the ni5010 */
}
/**************************************************************************
POLL - Wait for a frame
***************************************************************************/
static int ni5010_poll(struct nic *nic)
{
int rcv_stat;
if (((rcv_stat = inb(EDLC_RSTAT)) & RS_VALID_BITS) != RS_PKT_OK) {
outb(rcv_stat, EDLC_RSTAT); /* Clear the status */
return (0);
}
outb(rcv_stat, EDLC_RCLR); /* Clear the status */
nic->packetlen = inw(IE_RCNT);
/* Read packet into buffer */
outb(MM_MUX, IE_MMODE); /* Rcv buffer to system bus */
outw(0, IE_GP); /* Seek to beginning of packet */
insb(IE_RBUF, nic->packet, nic->packetlen);
return (1);
}
/**************************************************************************
TRANSMIT - Transmit a frame
***************************************************************************/
static void ni5010_transmit(struct nic *nic,
const char *d, /* Destination */
unsigned int t, /* Type */
unsigned int s, /* size */
const char *p) /* Packet */
{
unsigned int len;
int buf_offs, xmt_stat;
unsigned long time;
len = s + ETH_HLEN;
if (len < ETH_ZLEN)
len = ETH_ZLEN;
buf_offs = NI5010_BUFSIZE - len;
outb(0, EDLC_RMASK); /* Mask all receive interrupts */
outb(0, IE_MMODE); /* Put Xmit buffer on system bus */
outb(0xFF, EDLC_RCLR); /* Clear out pending rcv interrupts */
outw(buf_offs, IE_GP); /* Point GP at start of packet */
outsb(IE_XBUF, d, ETH_ALEN); /* Put dst in buffer */
outsb(IE_XBUF, nic->node_addr, ETH_ALEN);/* Put src in buffer */
outb(t >> 8, IE_XBUF);
outb(t, IE_XBUF);
outsb(IE_XBUF, p, s); /* Put data in buffer */
while (s++ < ETH_ZLEN - ETH_HLEN) /* Pad to min size */
outb(0, IE_XBUF);
outw(buf_offs, IE_GP); /* Rewrite where packet starts */
/* should work without that outb() (Crynwr used it) */
/*outb(MM_MUX, IE_MMODE);*/
/* Xmt buffer to EDLC bus */
outb(MM_EN_XMT | MM_MUX, IE_MMODE); /* Begin transmission */
/* wait for transmit complete */
while (((xmt_stat = inb(IE_ISTAT)) & IS_EN_XMT) != 0)
;
reset_receiver(); /* Immediately switch to receive */
}
/**************************************************************************
DISABLE - Turn off ethernet interface
***************************************************************************/
static void ni5010_disable(struct nic *nic)
{
outb(0, IE_MMODE);
outb(RS_RESET, EDLC_RESET);
}
static inline int rd_port(void)
{
inb(IE_RBUF);
return inb(IE_SAPROM);
}
static int ni5010_probe1(struct nic *nic)
{
int i, boguscount = 40, data;
/* The tests are from the Linux NI5010 driver
I don't understand it all, but if it works for them... */
if (inb(ioaddr) == 0xFF)
return (0);
while ((rd_port() & rd_port() & rd_port()
& rd_port() & rd_port() & rd_port()) != 0xFF)
{
if (boguscount-- <= 0)
return (0);
}
for (i = 0; i < 32; i++)
if ((data = rd_port()) != 0xFF)
break;
if (data == 0xFF)
return (0);
if (data == SA_ADDR0 && rd_port() == SA_ADDR1 && rd_port() == SA_ADDR2) {
for (i = 0; i < 4; i++)
rd_port();
if (rd_port() != NI5010_MAGICVAL1 || rd_port() != NI5010_MAGICVAL2)
return (0);
} else
return (0);
for (i = 0; i < ETH_ALEN; i++) {
outw(i, IE_GP);
nic->node_addr[i] = inb(IE_SAPROM);
}
printf("\nNI5010 ioaddr %#hX, addr %!\n", ioaddr, nic->node_addr);
/* get the size of the onboard receive buffer
* higher addresses than bufsize are wrapped into real buffer
* i.e. data for offs. 0x801 is written to 0x1 with a 2K onboard buffer
*/
if (bufsize_rcv == 0) {
outb(1, IE_MMODE); /* Put Rcv buffer on system bus */
outw(0, IE_GP); /* Point GP at start of packet */
outb(0, IE_RBUF); /* set buffer byte 0 to 0 */
for (i = 1; i < 0xFF; i++) {
outw(i << 8, IE_GP); /* Point GP at packet size to be tested */
outb(i, IE_RBUF);
outw(0x0, IE_GP); /* Point GP at start of packet */
data = inb(IE_RBUF);
if (data == i) break;
}
bufsize_rcv = i << 8;
outw(0, IE_GP); /* Point GP at start of packet */
outb(0, IE_RBUF); /* set buffer byte 0 to 0 again */
}
printf("Bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
return (1);
}
/**************************************************************************
PROBE - Look for an adapter, this routine's visible to the outside
***************************************************************************/
struct nic *ni5010_probe(struct nic *nic, unsigned short *probe_addrs)
{
static unsigned short io_addrs[] = {
0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0 };
unsigned short *p;
/* if probe_addrs is 0, then use list above */
if (probe_addrs == 0 || *probe_addrs == 0)
probe_addrs = io_addrs;
for (p = probe_addrs; (ioaddr = *p) != 0; p++) {
if (ni5010_probe1(nic))
break;
}
if (ioaddr == 0)
return (0);
ni5010_reset(nic);
/* point to NIC specific routines */
nic->reset = ni5010_reset;
nic->poll = ni5010_poll;
nic->transmit = ni5010_transmit;
nic->disable = ni5010_disable;
return (nic);
}

View file

@ -20,7 +20,8 @@ struct nic
void (*transmit)P((struct nic *, const char *d,
unsigned int t, unsigned int s, const char *p));
void (*disable)P((struct nic *));
char aui;
int flags; /* driver specific flags */
struct rom_info *rom_info; /* -> rom_info from main */
unsigned char *node_addr;
char *packet;
unsigned int packetlen;

View file

@ -252,9 +252,9 @@ static void ns8390_reset(struct nic *nic)
#endif
outb(D8390_COMMAND_PS1 |
D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND);
for (i=0; i<ETHER_ADDR_SIZE; i++)
for (i=0; i<ETH_ALEN; i++)
outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i);
for (i=0; i<ETHER_ADDR_SIZE; i++)
for (i=0; i<ETH_ALEN; i++)
outb(0xFF, eth_nic_base+D8390_P1_MAR0+i);
outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);
#ifdef INCLUDE_WD
@ -273,10 +273,10 @@ static void ns8390_reset(struct nic *nic)
/*
* 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
* 'flags' should have some compile time default value
* which can be changed from the command menu.
*/
t503_output = (nic->aui) ? 0 : _3COM_CR_XSEL;
t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL;
outb(t503_output, eth_asic_base + _3COM_CR);
#endif
}
@ -344,31 +344,15 @@ static void ns8390_transmit(
unsigned int s, /* size */
const char *p) /* Packet */
{
int c; /* used in ETHERBOOT16 */
#ifdef INCLUDE_3C503
if (!(eth_flags & FLAG_PIO)) {
#ifdef ETHERBOOT32
memcpy((void *)eth_bmem, d, ETHER_ADDR_SIZE); /* dst */
memcpy((void *)eth_bmem+ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE); /* src */
memcpy((char *)eth_bmem, d, ETH_ALEN); /* dst */
memcpy((char *)eth_bmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
*((char *)eth_bmem+12) = t>>8; /* type */
*((char *)eth_bmem+13) = t;
memcpy((void *)eth_bmem+ETHER_HDR_SIZE, p, s);
s += ETHER_HDR_SIZE;
while (s < ETH_MIN_PACKET) *((char *)eth_bmem+(s++)) = 0;
#endif
#ifdef ETHERBOOT16
memcpyf(eth_bmem, d, ETHER_ADDR_SIZE);
memcpyf(eth_bmem+ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE);
c = t >> 8;
memcpyf(eth_bmem+12, &c, 1);
c = t;
memcpyf(eth_bmem+13, &c, 1);
memcpyf((Address)(eth_bmem+ETHER_HDR_SIZE), p, s);
s += ETHER_HDR_SIZE;
if (s < ETH_MIN_PACKET)
bzerof(eth_bmem+s, ETH_MIN_PACKET-s), s = ETH_MIN_PACKET;
#endif
memcpy((char *)eth_bmem+ETH_HLEN, p, s);
s += ETH_HLEN;
while (s < ETH_ZLEN) *((char *)eth_bmem+(s++)) = 0;
}
#endif
@ -383,28 +367,13 @@ static void ns8390_transmit(
inb(0x84);
}
inb(0x84);
#ifdef ETHERBOOT32
memcpy((void *)eth_bmem, d, ETHER_ADDR_SIZE); /* dst */
memcpy((void *)eth_bmem+ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE); /* src */
memcpy((char *)eth_bmem, d, ETH_ALEN); /* dst */
memcpy((char *)eth_bmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
*((char *)eth_bmem+12) = t>>8; /* type */
*((char *)eth_bmem+13) = t;
memcpy((void *)eth_bmem+ETHER_HDR_SIZE, p, s);
s += ETHER_HDR_SIZE;
while (s < ETH_MIN_PACKET) *((char *)eth_bmem+(s++)) = 0;
#endif
#ifdef ETHERBOOT16
memcpyf(eth_bmem, d, ETHER_ADDR_SIZE);
memcpyf(eth_bmem+ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE);
c = t >> 8;
/* bcc generates worse code without (const+const) below */
memcpyf(eth_bmem+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE), &c, 1);
c = t;
memcpyf(eth_bmem+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE+1), &c, 1);
memcpyf((Address)(eth_bmem+ETHER_HDR_SIZE), p, s);
s += ETHER_HDR_SIZE;
if (s < ETH_MIN_PACKET)
bzerof(eth_bmem+s, ETH_MIN_PACKET-s), s = ETH_MIN_PACKET;
#endif
memcpy((char *)eth_bmem+ETH_HLEN, p, s);
s += ETH_HLEN;
while (s < ETH_ZLEN) *((char *)eth_bmem+(s++)) = 0;
if (eth_flags & FLAG_790) {
outb(0, eth_asic_base + WD_MSR);
inb(0x84);
@ -422,13 +391,13 @@ static void ns8390_transmit(
/* Programmed I/O */
unsigned short type;
type = (t >> 8) | (t << 8);
eth_pio_write(d, eth_tx_start<<8, ETHER_ADDR_SIZE);
eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETHER_ADDR_SIZE, ETHER_ADDR_SIZE);
eth_pio_write(d, eth_tx_start<<8, ETH_ALEN);
eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);
/* bcc generates worse code without (const+const) below */
eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETHER_ADDR_SIZE+ETHER_ADDR_SIZE), 2);
eth_pio_write(p, (eth_tx_start<<8)+ETHER_HDR_SIZE, s);
s += ETHER_HDR_SIZE;
if (s < ETH_MIN_PACKET) s = ETH_MIN_PACKET;
eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);
eth_pio_write(p, (eth_tx_start<<8)+ETH_HLEN, s);
s += ETH_HLEN;
if (s < ETH_ZLEN) s = ETH_ZLEN;
#endif
#if defined(INCLUDE_3C503)
}
@ -499,15 +468,12 @@ static int ns8390_poll(struct nic *nic)
if (eth_flags & FLAG_PIO)
eth_pio_read(pktoff, (char *)&pkthdr, 4);
else
#ifdef ETHERBOOT32
memcpy(&pkthdr, (void *)eth_rmem + pktoff, 4);
#endif
#ifdef ETHERBOOT16
fmemcpy(&pkthdr, eth_rmem + pktoff, 4);
#endif
memcpy(&pkthdr, (char *)eth_rmem + pktoff, 4);
pktoff += sizeof(pkthdr);
len = pkthdr.len - 4; /* sub CRC */
if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || pkthdr.len < ETH_MIN_PACKET) {
/* incoming length includes FCS so must sub 4 */
len = pkthdr.len - 4;
if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN
|| len > ETH_FRAME_LEN) {
printf("Bogus packet, ignoring\n");
return (0);
}
@ -520,12 +486,7 @@ static int ns8390_poll(struct nic *nic)
if (eth_flags & FLAG_PIO)
eth_pio_read(pktoff, p, frag);
else
#ifdef ETHERBOOT32
memcpy(p, (void *)eth_rmem + pktoff, frag);
#endif
#ifdef ETHERBOOT16
fmemcpy(p, eth_rmem + pktoff, frag);
#endif
memcpy(p, (char *)eth_rmem + pktoff, frag);
pktoff = eth_rx_start << 8;
p += frag;
len -= frag;
@ -534,12 +495,7 @@ static int ns8390_poll(struct nic *nic)
if (eth_flags & FLAG_PIO)
eth_pio_read(pktoff, p, len);
else
#ifdef ETHERBOOT32
memcpy(p, (void *)eth_rmem + pktoff, len);
#endif
#ifdef ETHERBOOT16
fmemcpy(p, eth_rmem + pktoff, len);
#endif
memcpy(p, (char *)eth_rmem + pktoff, len);
ret = 1;
}
#ifdef INCLUDE_WD
@ -581,9 +537,6 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
struct wd_board *brd;
unsigned short chksum;
unsigned char c;
#if defined(INCLUDE_WD) && defined(ETHERBOOT16)
unsigned char bmem13, bmem11;
#endif
eth_vendor = VENDOR_NONE;
eth_drain_receiver = 0;
@ -611,7 +564,7 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
for (brd = wd_boards; brd->name; brd++)
if (brd->id == c) break;
if (!brd->name) {
printf("Unknown WD/SMC NIC type %x\n", c);
printf("Unknown WD/SMC NIC type %hhX\n", c);
return (0); /* Unknown type */
}
eth_flags = brd->flags;
@ -624,23 +577,10 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
eth_memsize = MEM_16384;
}
if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {
#ifdef ETHERBOOT32
eth_bmem = (0x80000 |
((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));
#endif
#ifdef ETHERBOOT16
eth_bmem = inb(eth_asic_base + WD_MSR) & 0x3F;
eth_bmem <<= 13;
eth_bmem |= 0x80000;
#endif
} else
eth_bmem = WD_DEFAULT_MEM;
#ifdef ETHERBOOT16
/* cast is to force evaluation in long precision */
bmem13 = (Address)eth_bmem >> 13;
bmem11 = (Address)eth_bmem >> 11;
#endif
#ifdef ETHERBOOT32
if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
*((unsigned int *)(eth_bmem + 8192)) = (unsigned int)0;
if (*((unsigned int *)(eth_bmem + 8192))) {
@ -648,48 +588,23 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
eth_memsize = brd->memsize;
}
}
#endif
#ifdef ETHERBOOT16
if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {
i = 0;
memcpyf(eth_bmem + 8192, &i, sizeof(i));
if (!fbsame(eth_bmem + 8192, 0, sizeof(i))) {
brd += 2;
eth_memsize = brd->memsize;
}
}
#endif
outb(0x80, eth_asic_base + WD_MSR); /* Reset */
printf("\n%s base 0x%x, memory 0x%X, addr ",
brd->name, eth_asic_base, eth_bmem);
for (i=0; i<ETHER_ADDR_SIZE; i++) {
printf("%b",(int)(nic->node_addr[i] =
inb(i+eth_asic_base+WD_LAR)));
if (i < ETHER_ADDR_SIZE-1) printf (":");
for (i=0; i<ETH_ALEN; i++) {
nic->node_addr[i] = inb(i+eth_asic_base+WD_LAR);
}
printf("\n%s base %#hx, memory %#hx, addr %!\n",
brd->name, eth_asic_base, eth_bmem, nic->node_addr);
if (eth_flags & FLAG_790) {
outb(WD_MSR_MENB, eth_asic_base+WD_MSR);
outb((inb(eth_asic_base+0x04) |
0x80), eth_asic_base+0x04);
#ifdef ETHERBOOT32
outb((((unsigned)eth_bmem >> 13) & 0x0F) |
(((unsigned)eth_bmem >> 11) & 0x40) |
(inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
#endif
#ifdef ETHERBOOT16
outb((bmem13 & 0x0F) |
(bmem11 & 0x40) |
(inb(eth_asic_base+0x0B) & 0xB0), eth_asic_base+0x0B);
#endif
outb((inb(eth_asic_base+0x04) &
~0x80), eth_asic_base+0x04);
} else {
#ifdef ETHERBOOT32
outb((((unsigned)eth_bmem >> 13) & 0x3F) | 0x40, eth_asic_base+WD_MSR);
#endif
#ifdef ETHERBOOT16
outb((bmem13 & 0x3F) | 0x40, eth_asic_base+WD_MSR);
#endif
}
if (eth_flags & FLAG_16BIT) {
if (eth_flags & FLAG_790) {
@ -709,7 +624,6 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
}
inb(0x84);
}
putchar('\n');
#endif
#ifdef INCLUDE_3C503
/******************************************************************
@ -794,17 +708,16 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
/* Get our ethernet address */
outb(_3COM_CR_EALO | _3COM_CR_XSEL, eth_asic_base + _3COM_CR);
printf("\n3Com 3c503 base 0x%x, ", eth_nic_base);
printf("\n3Com 3c503 base %#hx, ", eth_nic_base);
if (eth_flags & FLAG_PIO)
printf("PIO mode");
else
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] =
inb(eth_nic_base+i)));
if (i < ETHER_ADDR_SIZE-1) printf (":");
printf("memory %#hx", eth_bmem);
for (i=0; i<ETH_ALEN; i++) {
nic->node_addr[i] = inb(eth_nic_base+i);
}
printf(", %s, addr %!\n", nic->flags ? "AUI" : "internal xcvr",
nic->node_addr);
outb(_3COM_CR_XSEL, eth_asic_base + _3COM_CR);
/*
* Initialize GA configuration register. Set bank and enable shared
@ -821,30 +734,18 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
*/
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);
}
#endif
#ifdef ETHERBOOT16
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.
*/
outb(eth_tx_start, eth_asic_base + _3COM_PSTR);
outb(eth_memsize, eth_asic_base + _3COM_PSPR);
printf ("\n");
}
#endif
#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)
@ -906,14 +807,12 @@ struct nic *eth_probe(struct nic *nic, unsigned short *probe_addrs)
eth_flags |= FLAG_16BIT;
eth_vendor = VENDOR_NOVELL;
eth_pio_read(0, romdata, sizeof(romdata));
printf("\nNE%c000 base 0x%x, addr ",
(eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base);
for (i=0; i<ETHER_ADDR_SIZE; i++) {
printf("%b",(int)(nic->node_addr[i] = romdata[i
+ ((eth_flags & FLAG_16BIT) ? i : 0)]));
if (i < ETHER_ADDR_SIZE-1) printf (":");
for (i=0; i<ETH_ALEN; i++) {
nic->node_addr[i] = romdata[i + ((eth_flags & FLAG_16BIT) ? i : 0)];
}
putchar('\n');
printf("\nNE%c000 base %#hx, addr %!\n",
(eth_flags & FLAG_16BIT) ? '2' : '1', eth_nic_base,
nic->node_addr);
}
#endif
if (eth_vendor == VENDOR_NONE)

View file

@ -6,6 +6,15 @@ Author: Martin Renters
**************************************************************************/
#define VENDOR_NONE 0
#define VENDOR_WD 1
#define VENDOR_NOVELL 2
#define VENDOR_3COM 3
#define FLAG_PIO 0x01
#define FLAG_16BIT 0x02
#define FLAG_790 0x04
#define MEM_8192 32
#define MEM_16384 64
#define MEM_32768 128

View file

@ -8,14 +8,51 @@
* your option) any later version.
*/
#if defined(__linux__) || defined(__FreeBSD__) || defined(GRUB)
#define ETHERBOOT32
#define ntohl(x) swap32(x)
#define htonl(x) swap32(x)
#define ntohs(x) swap16(x)
#define htons(x) swap16(x)
#define __LITTLE_ENDIAN /* x86 */
static inline unsigned long int swap32(unsigned long int x)
/* Taken from /usr/include/linux/hfs_sysdep.h */
#if defined(__BIG_ENDIAN)
# if !defined(__constant_htonl)
# define __constant_htonl(x) (x)
# endif
# if !defined(__constant_htons)
# define __constant_htons(x) (x)
# endif
#elif defined(__LITTLE_ENDIAN)
# if !defined(__constant_htonl)
# define __constant_htonl(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)))
# endif
# if !defined(__constant_htons)
# define __constant_htons(x) \
((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
(((unsigned short int)(x) & 0xff00) >> 8)))
# endif
#else
# error "Don't know if bytes are big- or little-endian!"
#endif
#define ntohl(x) \
(__builtin_constant_p(x) ? \
__constant_htonl((x)) : \
__swap32(x))
#define htonl(x) \
(__builtin_constant_p(x) ? \
__constant_htonl((x)) : \
__swap32(x))
#define ntohs(x) \
(__builtin_constant_p(x) ? \
__constant_htons((x)) : \
__swap16(x))
#define htons(x) \
(__builtin_constant_p(x) ? \
__constant_htons((x)) : \
__swap16(x))
static inline unsigned long int __swap32(unsigned long int x)
{
__asm__("xchgb %b0,%h0\n\t"
"rorl $16,%0\n\t"
@ -25,7 +62,7 @@ static inline unsigned long int swap32(unsigned long int x)
return x;
}
static inline unsigned short int swap16(unsigned short int x)
static inline unsigned short int __swap16(unsigned short int x)
{
__asm__("xchgb %b0,%h0"
: "=q" (x)
@ -33,38 +70,11 @@ static inline unsigned short int swap16(unsigned short int x)
return x;
}
#ifndef GRUB
# include "linux-asm-string.h"
#endif /* ! GRUB */
/* Make routines available to all */
#define swap32(x) __swap32(x)
#define swap16(x) __swap16(x)
#include "linux-asm-io.h"
#ifndef GRUB
#define _edata edata /* ELF does not prepend a _ */
#define _end end
#endif /* ! GRUB */
#endif
#ifdef __BCC__
#define ETHERBOOT16
#define inline
#define const
#define volatile
#define setjmp _setjmp /* they are that way in libc.a */
#define longjmp _longjmp
/* BCC include files are missing these. */
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
#endif
#if !defined(ETHERBOOT16) && !defined(ETHERBOOT32)
Error, neither ETHERBOOT16 nor ETHERBOOT32 defined
#endif
#if defined(ETHERBOOT16) && defined(ETHERBOOT32)
Error, both ETHERBOOT16 and ETHERBOOT32 defined
#endif
typedef unsigned long Address;

View file

@ -43,7 +43,7 @@ static struct txdesc txd;
#define NRXD 4
static struct rxdesc rxd[NRXD];
static int rxd_tail = 0;
#ifndef USE_INTERNAL_BUFFER
#ifdef USE_LOWMEM_BUFFER
#define rxb ((char *)0x10000 - NRXD * BUFLEN)
#define txb ((char *)0x10000 - NRXD * BUFLEN - BUFLEN)
#else
@ -51,7 +51,7 @@ static unsigned char rxb[NRXD * BUFLEN];
static unsigned char txb[BUFLEN];
#endif
static unsigned char ehdr[ETHER_HDR_SIZE]; /* buffer for ethernet header */
static unsigned char ehdr[ETH_HLEN]; /* buffer for ethernet header */
enum tulip_offsets {
CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28,
@ -270,17 +270,17 @@ static void tulip_transmit(struct nic *nic, const char *d, unsigned int t, unsig
/* 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;
memcpy(ehdr, d, ETH_ALEN);
memcpy(&ehdr[ETH_ALEN], nic->node_addr, ETH_ALEN);
ehdr[ETH_ALEN*2] = (t >> 8) & 0xff;
ehdr[ETH_ALEN*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.buf1sz = ETH_HLEN;
txd.buf2addr = p; /* packet to transmit */
txd.buf2sz = s;
@ -350,7 +350,7 @@ struct nic *otulip_probe(struct nic *nic, unsigned short *io_addrs, struct pci_d
membase = (unsigned int *)pci->membase;
/* wakeup chip */
pcibios_write_config_dword(0,pci->devfn,0x40,0x00000000);
pcibios_write_config_dword(pci->bus,pci->devfn,0x40,0x00000000);
/* Stop the chip's Tx and Rx processes. */
/* outl(inl(ioaddr + CSR6) & ~0x2002, ioaddr + CSR6); */
@ -359,12 +359,10 @@ struct nic *otulip_probe(struct nic *nic, unsigned short *io_addrs, struct pci_d
srom_read();
for (i=0; i < 6; i++)
for (i=0; i < ETH_ALEN; 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);
printf("Tulip %! at ioaddr %#hX\n", nic->node_addr, ioaddr);
tulip_reset(nic);

View file

@ -22,7 +22,7 @@
#include "pci.h"
/*#define DEBUG 1*/
static unsigned int pci_ioaddr = 0;
#define DEBUG 0
#ifdef CONFIG_PCI_DIRECT
#define PCIBIOS_SUCCESSFUL 0x00
@ -33,47 +33,47 @@ static unsigned int pci_ioaddr = 0;
#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn,
unsigned char where, unsigned char *value)
int pcibios_read_config_byte(unsigned int bus, unsigned int device_fn,
unsigned int where, unsigned char *value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
*value = inb(0xCFC + (where&3));
return PCIBIOS_SUCCESSFUL;
}
int pcibios_read_config_word (unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned short *value)
int pcibios_read_config_word (unsigned int bus,
unsigned int device_fn, unsigned int where, unsigned short *value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
*value = inw(0xCFC + (where&2));
return PCIBIOS_SUCCESSFUL;
}
static int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
unsigned char where, unsigned int *value)
int pcibios_read_config_dword (unsigned int bus, unsigned int device_fn,
unsigned int where, unsigned int *value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
*value = inl(0xCFC);
return PCIBIOS_SUCCESSFUL;
}
int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
unsigned char where, unsigned char value)
int pcibios_write_config_byte (unsigned int bus, unsigned int device_fn,
unsigned int where, unsigned char value)
{
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,
unsigned char where, unsigned short value)
int pcibios_write_config_word (unsigned int bus, unsigned int device_fn,
unsigned int where, unsigned short value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
outw(value, 0xCFC + (where&2));
return PCIBIOS_SUCCESSFUL;
}
int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned int value)
int pcibios_write_config_dword (unsigned int bus, unsigned int device_fn, unsigned int where, unsigned int value)
{
outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);
outl(value, 0xCFC);
@ -84,13 +84,12 @@ int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn, unsi
#else /* CONFIG_PCI_DIRECT not defined */
static unsigned long bios32_entry = 0;
static struct {
unsigned long address;
unsigned short segment;
} bios32_indirect = { 0, KERN_CODE_SEG };
static long pcibios_entry = 0;
static long pcibios_entry;
static struct {
unsigned long address;
unsigned short segment;
@ -106,10 +105,10 @@ static unsigned long bios32_service(unsigned long service)
save_flags(flags);
__asm__(
#ifndef ABSOLUTE_WITHOUT_ASTERISK
"lcall *(%%edi)"
#else
#ifdef ABSOLUTE_WITHOUT_ASTERISK
"lcall (%%edi)"
#else
"lcall *(%%edi)"
#endif
: "=a" (return_code),
"=b" (address),
@ -127,14 +126,14 @@ static unsigned long bios32_service(unsigned long service)
printf("bios32_service(%d) : not present\n", service);
return 0;
default: /* Shouldn't happen */
printf("bios32_service(%d) : returned 0x%x, mail drew@colorado.edu\n",
printf("bios32_service(%d) : returned %#X, mail drew@colorado.edu\n",
service, return_code);
return 0;
}
}
int pcibios_read_config_byte(unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned char *value)
int pcibios_read_config_byte(unsigned int bus,
unsigned int device_fn, unsigned int where, unsigned char *value)
{
unsigned long ret;
unsigned long bx = (bus << 8) | device_fn;
@ -142,10 +141,10 @@ int pcibios_read_config_byte(unsigned char bus,
save_flags(flags);
__asm__(
#ifndef ABSOLUTE_WITHOUT_ASTERISK
"lcall *(%%esi)\n\t"
#else
#ifdef ABSOLUTE_WITHOUT_ASTERISK
"lcall (%%esi)\n\t"
#else
"lcall *(%%esi)\n\t"
#endif
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@ -160,8 +159,8 @@ int pcibios_read_config_byte(unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
int pcibios_read_config_word(unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned short *value)
int pcibios_read_config_word(unsigned int bus,
unsigned int device_fn, unsigned int where, unsigned short *value)
{
unsigned long ret;
unsigned long bx = (bus << 8) | device_fn;
@ -169,10 +168,10 @@ int pcibios_read_config_word(unsigned char bus,
save_flags(flags);
__asm__(
#ifndef ABSOLUTE_WITHOUT_ASTERISK
"lcall *(%%esi)\n\t"
#else
#ifdef ABSOLUTE_WITHOUT_ASTERISK
"lcall (%%esi)\n\t"
#else
"lcall *(%%esi)\n\t"
#endif
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@ -187,8 +186,8 @@ int pcibios_read_config_word(unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
static int pcibios_read_config_dword(unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned int *value)
int pcibios_read_config_dword(unsigned int bus,
unsigned int device_fn, unsigned int where, unsigned int *value)
{
unsigned long ret;
unsigned long bx = (bus << 8) | device_fn;
@ -196,10 +195,10 @@ static int pcibios_read_config_dword(unsigned char bus,
save_flags(flags);
__asm__(
#ifndef ABSOLUTE_WITHOUT_ASTERISK
"lcall *(%%esi)\n\t"
#else
#ifdef ABSOLUTE_WITHOUT_ASTERISK
"lcall (%%esi)\n\t"
#else
"lcall *(%%esi)\n\t"
#endif
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@ -214,8 +213,8 @@ static int pcibios_read_config_dword(unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
int pcibios_write_config_byte (unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned char value)
int pcibios_write_config_byte (unsigned int bus,
unsigned int device_fn, unsigned int where, unsigned char value)
{
unsigned long ret;
unsigned long bx = (bus << 8) | device_fn;
@ -223,10 +222,10 @@ int pcibios_write_config_byte (unsigned char bus,
save_flags(flags); cli();
__asm__(
#ifndef ABSOLUTE_WITHOUT_ASTERISK
"lcall *(%%esi)\n\t"
#else
#ifdef ABSOLUTE_WITHOUT_ASTERISK
"lcall (%%esi)\n\t"
#else
"lcall *(%%esi)\n\t"
#endif
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@ -241,8 +240,8 @@ int pcibios_write_config_byte (unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
int pcibios_write_config_word (unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned short value)
int pcibios_write_config_word (unsigned int bus,
unsigned int device_fn, unsigned int where, unsigned short value)
{
unsigned long ret;
unsigned long bx = (bus << 8) | device_fn;
@ -250,10 +249,10 @@ int pcibios_write_config_word (unsigned char bus,
save_flags(flags); cli();
__asm__(
#ifndef ABSOLUTE_WITHOUT_ASTERISK
"lcall *(%%esi)\n\t"
#else
#ifdef ABSOLUTE_WITHOUT_ASTERISK
"lcall (%%esi)\n\t"
#else
"lcall *(%%esi)\n\t"
#endif
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@ -268,8 +267,8 @@ int pcibios_write_config_word (unsigned char bus,
return (int) (ret & 0xff00) >> 8;
}
int pcibios_write_config_dword (unsigned char bus,
unsigned char device_fn, unsigned char where, unsigned int value)
int pcibios_write_config_dword (unsigned int bus,
unsigned int device_fn, unsigned int where, unsigned int value)
{
unsigned long ret;
unsigned long bx = (bus << 8) | device_fn;
@ -277,10 +276,10 @@ int pcibios_write_config_dword (unsigned char bus,
save_flags(flags); cli();
__asm__(
#ifndef ABSOLUTE_WITHOUT_ASTERISK
"lcall *(%%esi)\n\t"
#else
#ifdef ABSOLUTE_WITHOUT_ASTERISK
"lcall (%%esi)\n\t"
#else
"lcall *(%%esi)\n\t"
#endif
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@ -309,10 +308,10 @@ static void check_pcibios(void)
save_flags(flags);
__asm__(
#ifndef ABSOLUTE_WITHOUT_ASTERISK
"lcall *(%%edi)\n\t"
#else
#ifdef ABSOLUTE_WITHOUT_ASTERISK
"lcall (%%edi)\n\t"
#else
"lcall *(%%edi)\n\t"
#endif
"jc 1f\n\t"
"xor %%ah, %%ah\n"
@ -335,8 +334,8 @@ static void check_pcibios(void)
}
#if DEBUG
if (pcibios_entry) {
printf ("pcibios_init : PCI BIOS revision %b.%b"
" entry at 0x%X\n", major_revision,
printf ("pcibios_init : PCI BIOS revision %hhX.%hhX"
" entry at %#X\n", major_revision,
minor_revision, pcibios_entry);
}
#endif
@ -348,6 +347,7 @@ static void pcibios_init(void)
union bios32 *check;
unsigned char sum;
int i, length;
unsigned long bios32_entry = 0;
/*
* Follow the standard procedure for locating the BIOS32 Service
@ -368,13 +368,13 @@ static void pcibios_init(void)
if (sum != 0)
continue;
if (check->fields.revision != 0) {
printf("pcibios_init : unsupported revision %d at 0x%X, mail drew@colorado.edu\n",
printf("pcibios_init : unsupported revision %d at %#X, mail drew@colorado.edu\n",
check->fields.revision, check);
continue;
}
#if DEBUG
printf("pcibios_init : BIOS32 Service Directory "
"structure at 0x%X\n", check);
"structure at %#X\n", check);
#endif
if (!bios32_entry) {
if (check->fields.entry >= 0x100000) {
@ -385,7 +385,7 @@ static void pcibios_init(void)
bios32_entry = check->fields.entry;
#if DEBUG
printf("pcibios_init : BIOS32 Service Directory"
" entry at 0x%X\n", bios32_entry);
" entry at %#X\n", bios32_entry);
#endif
bios32_indirect.address = bios32_entry;
}
@ -402,11 +402,16 @@ static void scan_bus(struct pci_device *pcidev)
unsigned char hdr_type = 0;
unsigned short vendor, device;
unsigned int membase, ioaddr, romaddr;
unsigned char class, subclass;
int i, reg;
unsigned int pci_ioaddr = 0;
pci_ioaddr = 0;
buses=1;
/* Scan all PCI buses, until we find our card.
* We could be smart only scan the required busses but that
* is error prone, and tricky.
* By scanning all possible pci busses in order we should find
* our card eventually.
*/
buses=256;
for (bus = 0; bus < buses; ++bus) {
for (devfn = 0; devfn < 0xff; ++devfn) {
if (PCI_FUNC (devfn) == 0)
@ -422,20 +427,16 @@ static void scan_bus(struct pci_device *pcidev)
vendor = l & 0xffff;
device = (l >> 16) & 0xffff;
/* check for pci-pci bridge devices!! - more buses when found */
pcibios_read_config_byte(bus, devfn, PCI_CLASS_CODE, &class);
pcibios_read_config_byte(bus, devfn, PCI_SUBCLASS_CODE, &subclass);
if (class == 0x06 && subclass == 0x04)
buses++;
#if DEBUG
printf("bus %x, function %x, vendor %x, device %x\n",
printf("bus %hhX, function %hhX, vendor %hX, device %hX\n",
bus, devfn, vendor, device);
#endif
for (i = 0; pcidev[i].vendor != 0; i++) {
if (vendor != pcidev[i].vendor
|| device != pcidev[i].dev_id)
continue;
pcidev[i].devfn = devfn;
pcidev[i].bus = bus;
for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
pcibios_read_config_dword(bus, devfn, reg, &ioaddr);
@ -449,14 +450,12 @@ static void scan_bus(struct pci_device *pcidev)
/* Get the ROM base address */
pcibios_read_config_dword(bus, devfn, PCI_ROM_ADDRESS, &romaddr);
romaddr >>= 10;
printf("Found %s at 0x%x, ROM address 0x%X\n",
printf("Found %s at %#hx, ROM address %#hx\n",
pcidev[i].name, ioaddr, romaddr);
/* Take the first one or the one that matches in boot ROM address */
if (pci_ioaddr == 0 || romaddr == ((unsigned long) rom.rom_segment << 4)) {
pcidev[i].membase = membase;
pcidev[i].ioaddr = ioaddr;
pcidev[i].devfn = devfn;
return;
}
}
@ -477,3 +476,26 @@ void eth_pci_init(struct pci_device *pcidev)
scan_bus(pcidev);
/* return values are in pcidev structures */
}
/*
* Set device to be a busmaster in case BIOS neglected to do so.
* Also adjust PCI latency timer to a reasonable value, 32.
*/
void adjust_pci_device(struct pci_device *p)
{
unsigned short new_command, pci_command;
unsigned char pci_latency;
pcibios_read_config_word(p->bus, p->devfn, PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
if (pci_command != new_command) {
printf("The PCI BIOS has not enabled this device!\nUpdating PCI command %hX->%hX. pci_bus %hhX pci_device_fn %hhX\n",
pci_command, new_command, p->bus, p->devfn);
pcibios_write_config_word(p->bus, p->devfn, PCI_COMMAND, new_command);
}
pcibios_read_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < 32) {
printf("PCI latency timer (CFLT) is unreasonably low at %d. Setting to 32 clocks.\n", pci_latency);
pcibios_write_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, 32);
}
}

View file

@ -22,6 +22,7 @@
*/
#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
#define PCI_COMMAND_MEM 0x2 /* Enable response in mem space */
#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
@ -41,6 +42,7 @@
#define PCI_DEVICE_ID 0x02 /* 16 bits */
#define PCI_COMMAND 0x04 /* 16 bits */
#define PCI_REVISION 0x08 /* 8 bits */
#define PCI_CLASS_CODE 0x0b /* 8 bits */
#define PCI_SUBCLASS_CODE 0x0a /* 8 bits */
#define PCI_HEADER_TYPE 0x0e /* 8 bits */
@ -101,12 +103,16 @@ __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
#define PCI_DEVICE_ID_REALTEK_8139 0x8139
#define PCI_VENDOR_ID_WINBOND2 0x1050
#define PCI_DEVICE_ID_WINBOND2_89C940 0x0940
#define PCI_DEVICE_ID_WINBOND2_89C840 0x0840
#define PCI_VENDOR_ID_COMPEX 0x11f6
#define PCI_DEVICE_ID_COMPEX_RL2000 0x1401
#define PCI_DEVICE_ID_COMPEX_RL100ATX 0x2011
#define PCI_VENDOR_ID_KTI 0x8e2e
#define PCI_DEVICE_ID_KTI_ET32P2 0x3000
#define PCI_VENDOR_ID_NETVIN 0x4a14
#define PCI_DEVICE_ID_NETVIN_NV5000SC 0x5000
#define PCI_VENDOR_ID_HOLTEK 0x12c3
#define PCI_DEVICE_ID_HOLTEK_HT80232 0x0058
#define PCI_VENDOR_ID_3COM 0x10b7
#define PCI_DEVICE_ID_3COM_3C590 0x5900
#define PCI_DEVICE_ID_3COM_3C595 0x5950
@ -120,8 +126,14 @@ __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
#define PCI_DEVICE_ID_3COM_3C905C_TXM 0x9200
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_82557 0x1229
#define PCI_DEVICE_ID_INTEL_82559ER 0x1209
#define PCI_DEVICE_ID_INTEL_ID1029 0x1029
#define PCI_DEVICE_ID_INTEL_ID1030 0x1030
#define PCI_DEVICE_ID_INTEL_82562 0x2449
#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_DEVICE_ID_AMD_LANCE 0x2000
#define PCI_VENDOR_ID_AMD_HOMEPNA 0x1022
#define PCI_DEVICE_ID_AMD_HOMEPNA 0x2001
#define PCI_VENDOR_ID_SMC_1211 0x1113
#define PCI_DEVICE_ID_SMC_1211 0x1211
#define PCI_VENDOR_ID_DEC 0x1011
@ -139,25 +151,42 @@ __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
#define PCI_DEVICE_ID_LC82C115 0xC115
#define PCI_VENDOR_ID_VIATEC 0x1106
#define PCI_DEVICE_ID_VIA_RHINE_I 0x3043
#define PCI_DEVICE_ID_VIA_VT6102 0x3065
#define PCI_DEVICE_ID_VIA_86C100A 0x6100
#define PCI_VENDOR_ID_DAVICOM 0x1282
#define PCI_DEVICE_ID_DM9009 0x9009
#define PCI_DEVICE_ID_DM9102 0x9102
#define PCI_VENDOR_ID_SIS 0x1039
#define PCI_DEVICE_ID_SIS900 0x0900
#define PCI_DEVICE_ID_SIS7016 0x7016
#define PCI_VENDOR_ID_DLINK 0x1186
#define PCI_DEVICE_ID_DFE530TXP 0x1300
#define PCI_VENDOR_ID_NS 0x100B
#define PCI_DEVICE_ID_DP83815 0x0020
#define PCI_VENDOR_ID_OLICOM 0x108d
#define PCI_DEVICE_ID_OLICOM_OC3136 0x0001
#define PCI_DEVICE_ID_OLICOM_OC2315 0x0011
#define PCI_DEVICE_ID_OLICOM_OC2325 0x0012
#define PCI_DEVICE_ID_OLICOM_OC2183 0x0013
#define PCI_DEVICE_ID_OLICOM_OC2326 0x0014
#define PCI_DEVICE_ID_OLICOM_OC6151 0x0021
struct pci_device {
unsigned short vendor, dev_id;
const char *name;
unsigned int membase;
unsigned short ioaddr;
unsigned short devfn;
unsigned char devfn;
unsigned char bus;
};
extern void eth_pci_init(struct pci_device *);
extern int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char *value);
extern int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn, unsigned char where, unsigned char value);
extern int pcibios_read_config_word(unsigned char bus, unsigned char device_fn, unsigned char where, unsigned short *value);
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);
extern int pcibios_read_config_byte(unsigned int bus, unsigned int device_fn, unsigned int where, unsigned char *value);
extern int pcibios_write_config_byte (unsigned int bus, unsigned int device_fn, unsigned int where, unsigned char value);
extern int pcibios_read_config_word(unsigned int bus, unsigned int device_fn, unsigned int where, unsigned short *value);
extern int pcibios_write_config_word (unsigned int bus, unsigned int device_fn, unsigned int where, unsigned short value);
extern int pcibios_read_config_dword(unsigned int bus, unsigned int device_fn, unsigned int where, unsigned int *value);
extern int pcibios_write_config_dword(unsigned int bus, unsigned int device_fn, unsigned int where, unsigned int value);
void adjust_pci_device(struct pci_device *p);
#endif /* PCI_H */

View file

@ -18,6 +18,10 @@
/*
06 Apr 2001 ken_yap@users.sourceforge.net (Ken Yap)
Following email from Hyun-Joon Cha, added a disable routine, otherwise
NIC remains live and can crash the kernel later.
4 Feb 2000 espenlaub@informatik.uni-ulm.de (Klaus Espenlaub)
Shuffled things around, removed the leftovers from the 8129 support
that was in the Linux driver and added a bit more 8139 definitions.
@ -60,6 +64,7 @@
#include "nic.h"
#include "pci.h"
#include "cards.h"
#include "timer.h"
#define RTL_TIMEOUT (1*TICKS_PER_SEC)
@ -70,7 +75,7 @@
#define RX_DMA_BURST 4 /* Maximum PCI burst, '4' is 256 bytes */
#define TX_DMA_BURST 4 /* Calculate as 16<<val. */
#define NUM_TX_DESC 4 /* Number of Tx descriptor registers. */
#define TX_BUF_SIZE (ETH_MAX_PACKET-4) /* FCS is added by the chip */
#define TX_BUF_SIZE ETH_FRAME_LEN /* FCS is added by the chip */
#define RX_BUF_LEN_IDX 0 /* 0, 1, 2 is allowed - 8,16,32K rx buffer */
#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
@ -160,13 +165,12 @@ static unsigned char tx_buffer[TX_BUF_SIZE] __attribute__((aligned(4)));
* states that we can do whatever we want below 0x10000 - so we do! */
/* 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)));
#else
#ifdef USE_LOWMEM_BUFFER
#define rx_ring ((unsigned char *)(0x10000 - (RX_BUF_LEN + 16)))
#else
static unsigned char rx_ring[RX_BUF_LEN+16] __attribute__((aligned(4)));
#endif
struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs,
struct pci_device *pci);
static int read_eeprom(int location);
@ -181,30 +185,17 @@ struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs,
struct pci_device *pci)
{
int i;
struct pci_device *p;
int speed10, fullduplex;
/* There are enough "RTL8139" strings on the console already, so
* be brief and concentrate on the interesting pieces of info... */
printf(" - ");
if (probeaddrs == 0 || probeaddrs[0] == 0) {
printf("\nERROR: no probeaddrs given, using pci_device\n");
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 %x)\n",
p->ioaddr, p->membase);
}
}
return 0;
}
/* Mask the bit that says "this is an io addr" */
ioaddr = probeaddrs[0] & ~3;
adjust_pci_device(pci);
/* Bring the chip out of low-power mode. */
outb(0x00, ioaddr + Config1);
@ -214,19 +205,14 @@ struct nic *rtl8139_probe(struct nic *nic, unsigned short *probeaddrs,
*ap++ = read_eeprom(i + 7);
} else {
unsigned char *ap = (unsigned char*)nic->node_addr;
for (i = 0; i < ETHER_ADDR_SIZE; i++)
for (i = 0; i < ETH_ALEN; i++)
*ap++ = inb(ioaddr + MAC0 + i);
}
printf("ioaddr 0x%x, addr ", ioaddr);
for (i = 0; i < ETHER_ADDR_SIZE; i++) {
printf("%b", nic->node_addr[i]);
if (i < ETHER_ADDR_SIZE-1) putchar(':');
}
speed10 = inb(ioaddr + MediaStatus) & MSRSpeed10;
fullduplex = inw(ioaddr + MII_BMCR) & BMCRDuplex;
printf(" %sMbps %s-duplex\n", speed10 ? "10" : "100",
printf("ioaddr %#hX, addr %! %sMbps %s-duplex\n", ioaddr,
nic->node_addr, speed10 ? "10" : "100",
fullduplex ? "full" : "half");
rtl_reset(nic);
@ -305,12 +291,12 @@ static void rtl_reset(struct nic* nic)
cur_rx = 0;
cur_tx = 0;
/* Check that the chip has finished the reset. */
for (i = 1000; i > 0; i--)
if ((inb(ioaddr + ChipCmd) & CmdReset) == 0)
break;
/* Give the chip 10ms to finish the reset. */
load_timer2(10*TICKS_PER_MS);
while ((inb(ioaddr + ChipCmd) & CmdReset) != 0 && timer2_running())
/* wait */;
for (i = 0; i < 6; i++)
for (i = 0; i < ETH_ALEN; i++)
outb(nic->node_addr[i], ioaddr + MAC0 + i);
/* Must enable Tx/Rx before setting transfer thresholds! */
@ -351,20 +337,20 @@ static void rtl_transmit(struct nic *nic, const char *destaddr,
unsigned int status, to, nstype;
unsigned long txstatus;
memcpy(tx_buffer, destaddr, ETHER_ADDR_SIZE);
memcpy(tx_buffer + ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE);
memcpy(tx_buffer, destaddr, ETH_ALEN);
memcpy(tx_buffer + ETH_ALEN, nic->node_addr, ETH_ALEN);
nstype = htons(type);
memcpy(tx_buffer + 2 * ETHER_ADDR_SIZE, (char*)&nstype, 2);
memcpy(tx_buffer + ETHER_HDR_SIZE, data, len);
memcpy(tx_buffer + 2 * ETH_ALEN, (char*)&nstype, 2);
memcpy(tx_buffer + ETH_HLEN, data, len);
len += ETHER_HDR_SIZE;
len += ETH_HLEN;
#ifdef DEBUG_TX
printf("sending %d bytes ethtype %x\n", len, type);
printf("sending %d bytes ethtype %hX\n", len, type);
#endif
/* Note: RTL8139 doesn't auto-pad, send minimum payload (another 4
* bytes are sent automatically for the FCS, totalling to 64 bytes). */
while (len < ETH_MIN_PACKET - 4) {
while (len < ETH_ZLEN) {
tx_buffer[len++] = '\0';
}
@ -386,14 +372,14 @@ static void rtl_transmit(struct nic *nic, const char *destaddr,
txstatus = inl(ioaddr+ TxStatus0 + cur_tx*4);
if (status & TxOK) {
cur_tx = ++cur_tx % NUM_TX_DESC;
cur_tx = (cur_tx + 1) % NUM_TX_DESC;
#ifdef DEBUG_TX
printf("tx done (%d ticks), status %x txstatus %X\n",
printf("tx done (%d ticks), status %hX txstatus %X\n",
to-currticks(), status, txstatus);
#endif
} else {
#ifdef DEBUG_TX
printf("tx timeout/error (%d ticks), status %x txstatus %X\n",
printf("tx timeout/error (%d ticks), status %hX txstatus %X\n",
currticks()-to, status, txstatus);
#endif
rtl_reset(nic);
@ -415,7 +401,7 @@ static int rtl_poll(struct nic *nic)
outw(status & ~(RxFIFOOver | RxOverflow | RxOK), ioaddr + IntrStatus);
#ifdef DEBUG_RX
printf("rtl_poll: int %x ", status);
printf("rtl_poll: int %hX ", status);
#endif
ring_offs = cur_rx % RX_BUF_LEN;
@ -424,8 +410,8 @@ static int rtl_poll(struct nic *nic)
rx_status &= 0xffff;
if ((rx_status & (RxBadSymbol|RxRunt|RxTooLong|RxCRCErr|RxBadAlign)) ||
(rx_size < ETH_MIN_PACKET) || (rx_size > ETH_MAX_PACKET)) {
printf("rx error %x\n", rx_status);
(rx_size < ETH_ZLEN) || (rx_size > ETH_FRAME_LEN + 4)) {
printf("rx error %hX\n", rx_status);
rtl_reset(nic); /* this clears all interrupts still pending */
return 0;
}
@ -447,7 +433,7 @@ static int rtl_poll(struct nic *nic)
#endif
}
#ifdef DEBUG_RX
printf(" at %X type %b%b rxstatus %x\n",
printf(" at %X type %hhX%hhX rxstatus %hX\n",
(unsigned long)(rx_ring+ring_offs+4),
nic->packet[12], nic->packet[13], rx_status);
#endif
@ -462,4 +448,11 @@ static int rtl_poll(struct nic *nic)
static void rtl_disable(struct nic *nic)
{
/* reset the chip */
outb(CmdReset, ioaddr + ChipCmd);
/* 10 ms timeout */
load_timer2(10*TICKS_PER_MS);
while ((inb(ioaddr + ChipCmd) & CmdReset) != 0 && timer2_running())
/* wait */;
}

1034
netboot/sis900.c Normal file

File diff suppressed because it is too large Load diff

363
netboot/sis900.h Normal file
View file

@ -0,0 +1,363 @@
/* -*- Mode:C; c-basic-offset:4; -*- */
/* Definitions for SiS ethernet controllers including 7014/7016 and 900
* References:
* SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support,
* preliminary Rev. 1.0 Jan. 14, 1998
* SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support,
* preliminary Rev. 1.0 Nov. 10, 1998
* SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
* preliminary Rev. 1.0 Jan. 18, 1998
* http://www.sis.com.tw/support/databook.htm
*/
/* MAC operationl registers of SiS 7016 and SiS 900 ethernet controller */
/* The I/O extent, SiS 900 needs 256 bytes of io address */
#define SIS900_TOTAL_SIZE 0x100
/* Symbolic offsets to registers. */
enum sis900_registers {
cr=0x0, /* Command Register */
cfg=0x4, /* Configuration Register */
mear=0x8, /* EEPROM Access Register */
ptscr=0xc, /* PCI Test Control Register */
isr=0x10, /* Interrupt Status Register */
imr=0x14, /* Interrupt Mask Register */
ier=0x18, /* Interrupt Enable Register */
epar=0x18, /* Enhanced PHY Access Register */
txdp=0x20, /* Transmit Descriptor Pointer Register */
txcfg=0x24, /* Transmit Configuration Register */
rxdp=0x30, /* Receive Descriptor Pointer Register */
rxcfg=0x34, /* Receive Configuration Register */
flctrl=0x38, /* Flow Control Register */
rxlen=0x3c, /* Receive Packet Length Register */
rfcr=0x48, /* Receive Filter Control Register */
rfdr=0x4C, /* Receive Filter Data Register */
pmctrl=0xB0, /* Power Management Control Register */
pmer=0xB4 /* Power Management Wake-up Event Register */
};
/* Symbolic names for bits in various registers */
enum sis900_command_register_bits {
RESET = 0x00000100,
SWI = 0x00000080,
RxRESET = 0x00000020,
TxRESET = 0x00000010,
RxDIS = 0x00000008,
RxENA = 0x00000004,
TxDIS = 0x00000002,
TxENA = 0x00000001
};
enum sis900_configuration_register_bits {
DESCRFMT = 0x00000100, /* 7016 specific */
REQALG = 0x00000080,
SB = 0x00000040,
POW = 0x00000020,
EXD = 0x00000010,
PESEL = 0x00000008,
LPM = 0x00000004,
BEM = 0x00000001
};
enum sis900_eeprom_access_reigster_bits {
MDC = 0x00000040,
MDDIR = 0x00000020,
MDIO = 0x00000010, /* 7016 specific */
EECS = 0x00000008,
EECLK = 0x00000004,
EEDO = 0x00000002,
EEDI = 0x00000001
};
enum sis900_interrupt_register_bits {
WKEVT = 0x10000000,
TxPAUSEEND = 0x08000000,
TxPAUSE = 0x04000000,
TxRCMP = 0x02000000,
RxRCMP = 0x01000000,
DPERR = 0x00800000,
SSERR = 0x00400000,
RMABT = 0x00200000,
RTABT = 0x00100000,
RxSOVR = 0x00010000,
HIBERR = 0x00008000,
SWINT = 0x00001000,
MIBINT = 0x00000800,
TxURN = 0x00000400,
TxIDLE = 0x00000200,
TxERR = 0x00000100,
TxDESC = 0x00000080,
TxOK = 0x00000040,
RxORN = 0x00000020,
RxIDLE = 0x00000010,
RxEARLY = 0x00000008,
RxERR = 0x00000004,
RxDESC = 0x00000002,
RxOK = 0x00000001
};
enum sis900_interrupt_enable_reigster_bits {
IE = 0x00000001
};
/* maximum dma burst fro transmission and receive*/
#define MAX_DMA_RANGE 7 /* actually 0 means MAXIMUM !! */
#define TxMXDMA_shift 20
#define RxMXDMA_shift 20
#define TX_DMA_BURST 0
#define RX_DMA_BURST 0
/* transmit FIFO threshholds */
#define TX_FILL_THRESH 16 /* 1/4 FIFO size */
#define TxFILLT_shift 8
#define TxDRNT_shift 0
#define TxDRNT_100 48 /* 3/4 FIFO size */
#define TxDRNT_10 16 /* 1/2 FIFO size */
enum sis900_transmit_config_register_bits {
TxCSI = 0x80000000,
TxHBI = 0x40000000,
TxMLB = 0x20000000,
TxATP = 0x10000000,
TxIFG = 0x0C000000,
TxFILLT = 0x00003F00,
TxDRNT = 0x0000003F
};
/* recevie FIFO thresholds */
#define RxDRNT_shift 1
#define RxDRNT_100 16 /* 1/2 FIFO size */
#define RxDRNT_10 24 /* 3/4 FIFO size */
enum sis900_reveive_config_register_bits {
RxAEP = 0x80000000,
RxARP = 0x40000000,
RxATX = 0x10000000,
RxAJAB = 0x08000000,
RxDRNT = 0x0000007F
};
#define RFAA_shift 28
#define RFADDR_shift 16
enum sis900_receive_filter_control_register_bits {
RFEN = 0x80000000,
RFAAB = 0x40000000,
RFAAM = 0x20000000,
RFAAP = 0x10000000,
RFPromiscuous = (RFAAB|RFAAM|RFAAP)
};
enum sis900_reveive_filter_data_mask {
RFDAT = 0x0000FFFF
};
/* EEPROM Addresses */
enum sis900_eeprom_address {
EEPROMSignature = 0x00,
EEPROMVendorID = 0x02,
EEPROMDeviceID = 0x03,
EEPROMMACAddr = 0x08,
EEPROMChecksum = 0x0b
};
/* The EEPROM commands include the alway-set leading bit. Refer to NM93Cxx datasheet */
enum sis900_eeprom_command {
EEread = 0x0180,
EEwrite = 0x0140,
EEerase = 0x01C0,
EEwriteEnable = 0x0130,
EEwriteDisable = 0x0100,
EEeraseAll = 0x0120,
EEwriteAll = 0x0110,
EEaddrMask = 0x013F,
};
/* Manamgement Data I/O (mdio) frame */
#define MIIread 0x6000
#define MIIwrite 0x5002
#define MIIpmdShift 7
#define MIIregShift 2
#define MIIcmdLen 16
#define MIIcmdShift 16
/* Buffer Descriptor Status*/
enum sis900_buffer_status {
OWN = 0x80000000,
MORE = 0x40000000,
INTR = 0x20000000,
SUPCRC = 0x10000000,
INCCRC = 0x10000000,
OK = 0x08000000,
DSIZE = 0x00000FFF
};
/* Status for TX Buffers */
enum sis900_tx_buffer_status {
ABORT = 0x04000000,
UNDERRUN = 0x02000000,
NOCARRIER = 0x01000000,
DEFERD = 0x00800000,
EXCDEFER = 0x00400000,
OWCOLL = 0x00200000,
EXCCOLL = 0x00100000,
COLCNT = 0x000F0000
};
enum sis900_rx_bufer_status {
OVERRUN = 0x02000000,
DEST = 0x00800000,
BCAST = 0x01800000,
MCAST = 0x01000000,
UNIMATCH = 0x00800000,
TOOLONG = 0x00400000,
RUNT = 0x00200000,
RXISERR = 0x00100000,
CRCERR = 0x00080000,
FAERR = 0x00040000,
LOOPBK = 0x00020000,
RXCOL = 0x00010000
};
/* MII register offsets */
enum mii_registers {
MII_CONTROL = 0x0000,
MII_STATUS = 0x0001,
MII_PHY_ID0 = 0x0002,
MII_PHY_ID1 = 0x0003,
MII_ANADV = 0x0004,
MII_ANLPAR = 0x0005,
MII_ANEXT = 0x0006
};
/* mii registers specific to SiS 900 */
enum sis_mii_registers {
MII_CONFIG1 = 0x0010,
MII_CONFIG2 = 0x0011,
MII_STSOUT = 0x0012,
MII_MASK = 0x0013
};
/* mii registers specific to AMD 79C901 */
enum amd_mii_registers {
MII_STATUS_SUMMARY = 0x0018
};
/* mii registers specific to ICS 1893 */
enum ics_mii_registers {
MII_EXTCTRL = 0x0010, MII_QPDSTS = 0x0011, MII_10BTOP = 0x0012,
MII_EXTCTRL2 = 0x0013
};
/* MII Control register bit definitions. */
enum mii_control_register_bits {
MII_CNTL_FDX = 0x0100,
MII_CNTL_RST_AUTO = 0x0200,
MII_CNTL_ISOLATE = 0x0400,
MII_CNTL_PWRDWN = 0x0800,
MII_CNTL_AUTO = 0x1000,
MII_CNTL_SPEED = 0x2000,
MII_CNTL_LPBK = 0x4000,
MII_CNTL_RESET = 0x8000
};
/* MII Status register bit */
enum mii_status_register_bits {
MII_STAT_EXT = 0x0001,
MII_STAT_JAB = 0x0002,
MII_STAT_LINK = 0x0004,
MII_STAT_CAN_AUTO = 0x0008,
MII_STAT_FAULT = 0x0010,
MII_STAT_AUTO_DONE = 0x0020,
MII_STAT_CAN_T = 0x0800,
MII_STAT_CAN_T_FDX = 0x1000,
MII_STAT_CAN_TX = 0x2000,
MII_STAT_CAN_TX_FDX = 0x4000,
MII_STAT_CAN_T4 = 0x8000
};
#define MII_ID1_OUI_LO 0xFC00 /* low bits of OUI mask */
#define MII_ID1_MODEL 0x03F0 /* model number */
#define MII_ID1_REV 0x000F /* model number */
/* MII NWAY Register Bits ...
valid for the ANAR (Auto-Negotiation Advertisement) and
ANLPAR (Auto-Negotiation Link Partner) registers */
enum mii_nway_register_bits {
MII_NWAY_NODE_SEL = 0x001f,
MII_NWAY_CSMA_CD = 0x0001,
MII_NWAY_T = 0x0020,
MII_NWAY_T_FDX = 0x0040,
MII_NWAY_TX = 0x0080,
MII_NWAY_TX_FDX = 0x0100,
MII_NWAY_T4 = 0x0200,
MII_NWAY_PAUSE = 0x0400,
MII_NWAY_RF = 0x2000,
MII_NWAY_ACK = 0x4000,
MII_NWAY_NP = 0x8000
};
enum mii_stsout_register_bits {
MII_STSOUT_LINK_FAIL = 0x4000,
MII_STSOUT_SPD = 0x0080,
MII_STSOUT_DPLX = 0x0040
};
enum mii_stsics_register_bits {
MII_STSICS_SPD = 0x8000, MII_STSICS_DPLX = 0x4000,
MII_STSICS_LINKSTS = 0x0001
};
enum mii_stssum_register_bits {
MII_STSSUM_LINK = 0x0008,
MII_STSSUM_DPLX = 0x0004,
MII_STSSUM_AUTO = 0x0002,
MII_STSSUM_SPD = 0x0001
};
enum sis900_revision_id {
SIS630A_900_REV = 0x80, SIS630E_900_REV = 0x81,
SIS630S_900_REV = 0x82, SIS630EA1_900_REV = 0x83
};
enum sis630_revision_id {
SIS630A0 = 0x00, SIS630A1 = 0x01,
SIS630B0 = 0x10, SIS630B1 = 0x11
};
#define FDX_CAPABLE_DUPLEX_UNKNOWN 0
#define FDX_CAPABLE_HALF_SELECTED 1
#define FDX_CAPABLE_FULL_SELECTED 2
#define HW_SPEED_UNCONFIG 0
#define HW_SPEED_HOME 1
#define HW_SPEED_10_MBPS 10
#define HW_SPEED_100_MBPS 100
#define HW_SPEED_DEFAULT (HW_SPEED_100_MBPS)
#define CRC_SIZE 4
#define MAC_HEADER_SIZE 14
#define TX_BUF_SIZE 1536
#define RX_BUF_SIZE 1536
#define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
/* Time in ticks before concluding the transmitter is hung. */
#define TX_TIMEOUT (4*TICKS_PER_SEC)
typedef struct _BufferDesc {
u32 link;
volatile u32 cmdsts;
u32 bufptr;
} BufferDesc;

91
netboot/sis900.txt Normal file
View file

@ -0,0 +1,91 @@
How I added the SIS900 card to Etherboot
Author: Marty Connor (mdc@thinguin.org)
Date: 25 Febrary 2001
Description:
This file is intended to help people who want to write an Etherboot
driver or port another driver to Etherboot. It is a starting point.
Perhaps someday I may write a more detailed description of writing an
Etherboot driver. This text should help get people started, and
studying sis900.[ch] should help show the basic structure and
techniques involved in writing and Etherboot driver.
***********************************************************************
0. Back up all the files I need to modify:
cd etherboot-4.7.20/src
cp Makefile Makefile.orig
cp config.c config.c.orig
cp pci.h pci.h.orig
cp NIC NIC.orig
cp cards.h cards.h.orig
1. Edit src/Makefile to add SIS900FLAGS to defines
SIS900FLAGS= -DINCLUDE_SIS900
2. edit src/pci.h to add PCI signatures for card
#define PCI_VENDOR_ID_SIS 0x1039
#define PCI_DEVICE_ID_SIS900 0x0900
#define PCI_DEVICE_ID_SIS7016 0x7016
3. Edit src/config.c to add the card to the card probe list
#if defined(INCLUDE_NS8390) || defined(INCLUDE_EEPRO100) ||
defined(INCLUDE_LANCE) || defined(INCLUDE_EPIC100) ||
defined(INCLUDE_TULIP) || defined(INCLUDE_OTULIP) ||
defined(INCLUDE_3C90X) || defined(INCLUDE_3C595) ||
defined(INCLUDE_RTL8139) || defined(INCLUDE_VIA_RHINE) ||
defined(INCLUDE_SIS900) || defined(INCLUDE_W89C840)
... and ...
#ifdef INCLUDE_SIS900
{ PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900,
"SIS900", 0, 0, 0, 0},
{ PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016,
"SIS7016", 0, 0, 0, 0},
#endif
... and ...
#ifdef INCLUDE_SIS900
{ "SIS900", sis900_probe, pci_ioaddrs },
#endif
4. Edit NIC to add sis900 and sis7016 to NIC list
# SIS 900 and SIS 7016
sis900 sis900 0x1039,0x0900
sis7016 sis900 0x1039,0x7016
5. Edit cards.h to add sis900 probe routine declaration
#ifdef INCLUDE_SIS900
extern struct nic *sis900_probe(struct nic *, unsigned short *
PCI_ARG(struct pci_device *));
#endif
***********************************************************************
At this point, you can begin creating your driver source file. See
the "Writing and Etherboot Driver" section of the Etherboot
documentation for some hints. See the skel.c file for a starting
point. If there is a Linux driver for the card, you may be able to
use that. Copy and learn from existing Etherboot drivers (this is GPL
/ Open Source software!).
Join the etherboot-developers and etherboot-users mailing lists
(information is on etherboot.sourceforge.net) for information and
assistance. We invite more developers to help improve Etherboot.
Visit the http://etherboot.sourceforge.net, http://thinguin.org,
http://rom-o-matic.net, and http://ltsp.org sites for information and
assistance.
Enjoy.

View file

@ -514,7 +514,7 @@ static int SK_poll(struct nic *nic)
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",
PRINTF2(("## %s: At beginning of SK_poll(). CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0)));
p = nic->priv_data;
@ -529,7 +529,7 @@ static int SK_poll(struct nic *nic)
if (csr0 & CSR0_ERR) /* LANCE Error */
{
printf("%s: error: 0x%x", SK_NAME, csr0);
printf("%s: error: %#hX", SK_NAME, csr0);
if (csr0 & CSR0_MISS) /* No place to store packet ? */
{
@ -576,7 +576,7 @@ static int SK_poll(struct nic *nic)
}
else if (rmdstat & RX_ERR) /* Receive Error ? */
{
printf("%s: RX error: 0x%x\n", SK_NAME, (int) rmdstat);
printf("%s: RX error: %#hX\n", SK_NAME, (int) rmdstat);
rmdp->u.s.status = RX_OWN; /* Relinquish ownership to LANCE */
}
else /* We have a packet which can be queued for the upper layers */
@ -628,20 +628,20 @@ const char *pack) /* Packet */
short len;
int csr0, i, tmdstat;
PRINTF2(("## %s: At beginning of SK_transmit(). CSR0: 0x%X\n",
PRINTF2(("## %s: At beginning of SK_transmit(). CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0)));
p = nic->priv_data;
tmdp = p->tmdhead + p->tmdnum; /* Which descriptor for transmitting */
/* Copy data into dual ported ram */
memcpy(&p->ram->tmdbuf[p->tmdnum][0], d, ETHER_ADDR_SIZE); /* dst */
memcpy(&p->ram->tmdbuf[p->tmdnum][ETHER_ADDR_SIZE], nic->node_addr, ETHER_ADDR_SIZE); /* src */
p->ram->tmdbuf[p->tmdnum][ETHER_ADDR_SIZE + ETHER_ADDR_SIZE] = t >> 8; /* type */
p->ram->tmdbuf[p->tmdnum][ETHER_ADDR_SIZE + ETHER_ADDR_SIZE + 1] = t; /* type */
memcpy(&p->ram->tmdbuf[p->tmdnum][ETHER_HDR_SIZE], pack, s);
s += ETHER_HDR_SIZE;
while (s < ETH_MIN_PACKET) /* pad to min length */
memcpy(&p->ram->tmdbuf[p->tmdnum][0], d, ETH_ALEN); /* dst */
memcpy(&p->ram->tmdbuf[p->tmdnum][ETH_ALEN], nic->node_addr, ETH_ALEN); /* src */
p->ram->tmdbuf[p->tmdnum][ETH_ALEN + ETH_ALEN] = t >> 8; /* type */
p->ram->tmdbuf[p->tmdnum][ETH_ALEN + ETH_ALEN + 1] = t; /* type */
memcpy(&p->ram->tmdbuf[p->tmdnum][ETH_HLEN], pack, s);
s += ETH_HLEN;
while (s < ETH_ZLEN) /* pad to min length */
p->ram->tmdbuf[p->tmdnum][s++] = 0;
p->ram->tmde[p->tmdnum].status2 = 0x0;
@ -674,7 +674,7 @@ const char *pack) /* Packet */
if (csr0 & CSR0_ERR) /* LANCE Error */
{
printf("%s: error: 0x%x", SK_NAME, csr0);
printf("%s: error: %#hX", SK_NAME, csr0);
if (csr0 & CSR0_MISS) /* No place to store packet ? */
{
@ -696,7 +696,7 @@ const char *pack) /* Packet */
*/
if (tmdstat & TX_ERR) /* Error occurred */
{
printf("%s: TX error: 0x%x 0x%x\n", SK_NAME, (int) tmdstat,
printf("%s: TX error: %#hX %#hX\n", SK_NAME, (int) tmdstat,
(int) tmdp->status2);
if (tmdp->status2 & TX_TDR) /* TDR problems? */
@ -730,9 +730,9 @@ DISABLE - Turn off ethernet interface
***************************************************************************/
static void SK_disable(struct nic *nic)
{
PRINTF(("## %s: At beginning of SK_disable(). CSR0: 0x%X\n",
PRINTF(("## %s: At beginning of SK_disable(). CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0)));
PRINTF(("%s: Shutting %s down CSR0 0x%X\n", SK_NAME, SK_NAME,
PRINTF(("%s: Shutting %s down CSR0 %#hX\n", SK_NAME, SK_NAME,
(int) SK_read_reg(CSR0)));
SK_write_reg(CSR0, CSR0_STOP); /* STOP the LANCE */
@ -788,7 +788,7 @@ int SK_probe1(struct nic *nic, short ioaddr1)
* Now here we could use a routine which searches for a free
* place in the ram and set SK_ADDR if found. TODO.
*/
printf("%s: SK_ADDR 0x%X is not valid. Check configuration.\n",
printf("%s: SK_ADDR %#hX is not valid. Check configuration.\n",
SK_NAME, SK_ADDR);
return -1;
}
@ -803,11 +803,11 @@ int SK_probe1(struct nic *nic, short ioaddr1)
#endif
board = (SK_RAM *) rom_addr;
PRINTF(("adr[0]: %x, adr[1]: %x, adr[2]: %x\n",
PRINTF(("adr[0]: %hX, adr[1]: %hX, adr[2]: %hX\n",
board->rom[0], board->rom[2], board->rom[4]));
/* Read in station address */
for (i = 0, j = 0; i < ETHER_ADDR_SIZE; i++, j+=2)
for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2)
{
*(nic->node_addr+i) = board->rom[j];
}
@ -832,15 +832,8 @@ int SK_probe1(struct nic *nic, short ioaddr1)
p->tmdhead = &(p->ram)->tmde[0]; /* Set TMD head */
p->rmdhead = &(p->ram)->rmde[0]; /* Set RMD head */
printf("Schneider & Koch G16 at 0x%x, mem at 0x%X, HW addr: %b:%b:%b:%b:%b:%b\n",
(unsigned int) ioaddr,
(unsigned int) p->ram,
*(nic->node_addr+0),
*(nic->node_addr+1),
*(nic->node_addr+2),
*(nic->node_addr+3),
*(nic->node_addr+4),
*(nic->node_addr+5));
printf("Schneider & Koch G16 at %#hX, mem at %#hX, HW addr: %!\n",
(unsigned int) ioaddr, (unsigned int) p->ram, nic->node_addr);
/* Initialize buffer pointers */
@ -865,19 +858,19 @@ int SK_probe1(struct nic *nic, short ioaddr1)
* then stop again and reinit with NORMAL_MODE
*/
printf("## %s: After lance init. CSR0: 0x%X\n",
printf("## %s: After lance init. CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0));
SK_write_reg(CSR0, CSR0_STOP);
printf("## %s: LANCE stopped. CSR0: 0x%X\n",
printf("## %s: LANCE stopped. CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0));
SK_lance_init(nic, MODE_DTX | MODE_DRX);
printf("## %s: Reinit with DTX + DRX off. CSR0: 0x%X\n",
printf("## %s: Reinit with DTX + DRX off. CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0));
SK_write_reg(CSR0, CSR0_STOP);
printf("## %s: LANCE stopped. CSR0: 0x%X\n",
printf("## %s: LANCE stopped. CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0));
SK_lance_init(nic, MODE_NORMAL);
printf("## %s: LANCE back to normal mode. CSR0: 0x%X\n",
printf("## %s: LANCE back to normal mode. CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0));
SK_print_pos(nic, "POS regs before returning OK");
@ -887,7 +880,7 @@ int SK_probe1(struct nic *nic, short ioaddr1)
else /* LANCE init failed */
{
PRINTF(("## %s: LANCE init failed: CSR0: 0x%X\n",
PRINTF(("## %s: LANCE init failed: CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0)));
return -1;
}
@ -908,7 +901,7 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
struct tmd *tmdp;
struct rmd *rmdp;
PRINTF(("## %s: At beginning of LANCE init. CSR0: 0x%X\n",
PRINTF(("## %s: At beginning of LANCE init. CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0)));
/* Reset LANCE */
@ -957,7 +950,7 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
(p->ram)->ib.mode = mode; /* Set operation mode */
for (i = 0; i < ETHER_ADDR_SIZE; i++) /* Set physical address */
for (i = 0; i < ETH_ALEN; i++) /* Set physical address */
{
(p->ram)->ib.paddr[i] = *(nic->node_addr+i);
}
@ -995,7 +988,7 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
SK_write_reg(CSR2, 0); /* Set high order bits 23:16 */
PRINTF(("## %s: After setting CSR1-3. CSR0: 0x%X\n",
PRINTF(("## %s: After setting CSR1-3. CSR0: %#hX\n",
SK_NAME, SK_read_reg(CSR0)));
/* Initialize LANCE */
@ -1016,8 +1009,8 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
if (i >= 100) /* Something is wrong ! */
{
printf("%s: can't init am7990, status: 0x%x "
"init_block: 0x%X\n",
printf("%s: can't init am7990, status: %#hX "
"init_block: %#hX\n",
SK_NAME, (int) SK_read_reg(CSR0),
(unsigned int) &(p->ram)->ib);
@ -1034,7 +1027,7 @@ static int SK_lance_init(struct nic *nic, unsigned short mode)
SK_write_reg(CSR0, CSR0_IDON | CSR0_INEA | CSR0_STRT);
PRINTF(("## %s: LANCE started. CSR0: 0x%X\n", SK_NAME,
PRINTF(("## %s: LANCE started. CSR0: %#hX\n", SK_NAME,
SK_read_reg(CSR0)));
return 0; /* LANCE is up and running */
@ -1122,7 +1115,7 @@ static void SK_print_pos(struct nic *nic, char *text)
printf("## %s: %s.\n"
"## pos0=0x%x pos1=0x%x pos2=0x%x pos3=0x%X pos4=0x%x\n",
"## pos0=%#hX pos1=%#hX pos2=%#hX pos3=%#hX pos4=%#hX\n",
SK_NAME, text, pos0, pos1, pos2, (pos3<<14), pos4);
} /* End of SK_print_pos() */
@ -1134,7 +1127,7 @@ static void SK_print_ram(struct nic *nic)
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",
"## RAM at %#hX tmdhead: %#hX rmdhead: %#hX initblock: %#hX\n",
SK_NAME,
(unsigned int) p->ram,
(unsigned int) p->tmdhead,
@ -1149,7 +1142,7 @@ static void SK_print_ram(struct nic *nic)
{
printf("\n## ");
}
printf("tmdbufs%d: 0x%X ", (i+1), (int) p->tmdbufs[i]);
printf("tmdbufs%d: %#hX ", (i+1), (int) p->tmdbufs[i]);
}
printf("## ");
@ -1159,7 +1152,7 @@ static void SK_print_ram(struct nic *nic)
{
printf("\n## ");
}
printf("rmdbufs%d: 0x%X ", (i+1), (int) p->rmdbufs[i]);
printf("rmdbufs%d: %#hX ", (i+1), (int) p->rmdbufs[i]);
}
putchar('\n');

View file

@ -134,7 +134,7 @@ static int smc_probe( int ioaddr )
if (ioaddr != (base_address_register >> 3 & 0x3E0)) {
#ifdef SMC9000_VERBOSE
printf("SMC9000: IOADDR %x doesn't match configuration (%x)."
printf("SMC9000: IOADDR %hX doesn't match configuration (%hX)."
"Probably not a SMC chip\n",
ioaddr, base_address_register >> 3 & 0x3E0);
#endif
@ -152,8 +152,8 @@ static int smc_probe( int ioaddr )
if (!chip_ids[(revision_register >> 4) & 0xF]) {
/* I don't recognize this chip, so... */
#ifdef SMC9000_VERBOSE
printf("SMC9000: IO %x: Unrecognized revision register:"
" %x, Contact author.\n", ioaddr, revision_register);
printf("SMC9000: IO %hX: Unrecognized revision register:"
" %hX, Contact author.\n", ioaddr, revision_register);
#endif
return -1;
}
@ -192,7 +192,7 @@ static void smc9000_transmit(
int i;
/* We dont pad here since we can have the hardware doing it for us */
length = (s + ETHER_HDR_SIZE + 1)&~1;
length = (s + ETH_HLEN + 1)&~1;
/* convert to MMU pages */
numPages = length / 256;
@ -245,7 +245,7 @@ static void smc9000_transmit(
_outw(PTR_AUTOINC, smc9000_base + POINTER);
#if SMC9000_DEBUG > 2
printf("Trying to xmit packet of length %x\n", length );
printf("Trying to xmit packet of length %hX\n", length );
#endif
/* send the packet length ( +6 for status, length and ctl byte )
@ -259,8 +259,8 @@ static void smc9000_transmit(
/* 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);
outsw(smc9000_base + DATA_1, d, ETH_ALEN >> 1);
outsw(smc9000_base + DATA_1, nic->node_addr, ETH_ALEN >> 1);
_outw(htons(t), smc9000_base + DATA_1);
/* ... the data ... */
@ -300,7 +300,7 @@ static void smc9000_transmit(
if (0 == (tx_status & TS_SUCCESS)) {
#ifdef SMC9000_VERBOSE
printf("SMC9000: TX FAIL STATUS: %x \n", tx_status);
printf("SMC9000: TX FAIL STATUS: %hX \n", tx_status);
#endif
/* re-enable transmit */
SMC_SELECT_BANK(smc9000_base, 0);
@ -476,16 +476,13 @@ struct nic *smc9000_probe(struct nic *nic, unsigned short *probe_addrs)
/* 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",
printf("%s rev:%d I/O port:%hX Interface:%s RAM:%d bytes \n",
version_string, revision & 0xF,
smc9000_base, if_string, memory );
/*
* Print the Ethernet address
*/
printf("Ethernet MAC address: ");
for (i = 0; i < 5; i++)
printf("%b:", nic->node_addr[i]);
printf("%b\n", nic->node_addr[5]);
printf("Ethernet MAC address: %!\n", nic->node_addr);
SMC_SELECT_BANK(smc9000_base, 0);

View file

@ -125,7 +125,7 @@ static void tiara_reset(struct nic *nic)
while ((inb(ioaddr + DLCR_RECV_MODE) & BUF_EMPTY) == 0)
inb(ioaddr + BMPR_MEM_PORT);
/* Set node address */
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
for (i = 0; i < ETH_ALEN; ++i)
outb(nic->node_addr[i], ioaddr + DLCR_NODE_ID + i);
outb(CLR_RCV_STATUS, ioaddr + DLCR_RECV_STAT);
outb(CARD_ENABLE, ioaddr + DLCR_ENABLE);
@ -145,11 +145,11 @@ static int tiara_poll(struct nic *nic)
len = inw(ioaddr + BMPR_MEM_PORT); /* throw away status */
len = inw(ioaddr + BMPR_MEM_PORT);
/* Drop overlength packets */
if (len > ETH_MAX_PACKET)
if (len > ETH_FRAME_LEN)
return (0); /* should we drain the buffer? */
insw(ioaddr + BMPR_MEM_PORT, nic->packet, len / 2);
/* If it's our own, drop it */
if (memcmp(nic->packet + ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE) == 0)
if (memcmp(nic->packet + ETH_ALEN, nic->node_addr, ETH_ALEN) == 0)
return (0);
nic->packetlen = len;
return (1);
@ -168,17 +168,17 @@ const char *p) /* Packet */
unsigned int len;
unsigned long time;
len = s + ETHER_HDR_SIZE;
if (len < ETH_MIN_PACKET)
len = ETH_MIN_PACKET;
len = s + ETH_HLEN;
if (len < ETH_ZLEN)
len = ETH_ZLEN;
t = htons(t);
outsw(ioaddr + BMPR_MEM_PORT, d, ETHER_ADDR_SIZE / 2);
outsw(ioaddr + BMPR_MEM_PORT, nic->node_addr, ETHER_ADDR_SIZE / 2);
outsw(ioaddr + BMPR_MEM_PORT, d, ETH_ALEN / 2);
outsw(ioaddr + BMPR_MEM_PORT, nic->node_addr, ETH_ALEN / 2);
outw(t, ioaddr + BMPR_MEM_PORT);
outsw(ioaddr + BMPR_MEM_PORT, p, s / 2);
if (s & 1) /* last byte */
outb(p[s-1], ioaddr + BMPR_MEM_PORT);
while (s++ < ETH_MIN_PACKET - ETHER_HDR_SIZE) /* pad */
while (s++ < ETH_ZLEN - ETH_HLEN) /* pad */
outb(0, ioaddr + BMPR_MEM_PORT);
outw(len | (TMST << 8), ioaddr + BMPR_PKT_LEN);
/* wait for transmit complete */
@ -206,20 +206,13 @@ static int tiara_probe1(struct nic *nic)
static char all_ones[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
int i;
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
for (i = 0; i < ETH_ALEN; ++i)
nic->node_addr[i] = inb(ioaddr + PROM_ID + i);
if (memcmp(nic->node_addr, vendor_prefix, sizeof(vendor_prefix)) != 0)
return (0);
if (memcmp(nic->node_addr, all_ones, sizeof(all_ones)) == 0)
return (0);
printf("\nTiara ioaddr 0x%x, addr ", ioaddr);
for (i = 0; i < ETHER_ADDR_SIZE; ++i)
{
printf("%b", nic->node_addr[i]);
if (i < ETHER_ADDR_SIZE - 1)
printf(":");
}
putchar('\n');
printf("\nTiara ioaddr %#hX, addr %!\n", ioaddr, nic->node_addr);
return (1);
}

127
netboot/timer.c Normal file
View file

@ -0,0 +1,127 @@
/* A couple of routines to implement a low-overhead timer for drivers */
/*
* This program is free software; you can redistribute 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 "timer.h"
void load_timer2(unsigned int ticks)
{
/* Set up the timer gate, turn off the speaker */
outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
outb(ticks & 0xFF, TIMER2_PORT);
outb(ticks >> 8, TIMER2_PORT);
}
#if defined(CONFIG_TSC_CURRTICKS)
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
#define rdtscll(val) \
__asm__ __volatile__ ("rdtsc" : "=A" (val))
#define HZ TICKS_PER_SEC
#define CLOCK_TICK_RATE 1193180U /* Underlying HZ */
/* LATCH is used in the interval timer and ftape setup. */
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
/* ------ Calibrate the TSC -------
* Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
* Too much 64-bit arithmetic here to do this cleanly in C, and for
* accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
* output busy loop as low as possible. We avoid reading the CTC registers
* directly because of the awkward 8-bit access mechanism of the 82C54
* device.
*/
#define CALIBRATE_LATCH (5 * LATCH)
static unsigned long long calibrate_tsc(void)
{
/* Set the Gate high, disable speaker */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
/*
* Now let's take care of CTC channel 2
*
* Set the Gate high, program CTC channel 2 for mode 0,
* (interrupt on terminal count mode), binary count,
* load 5 * LATCH count, (LSB and MSB) to begin countdown.
*/
outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */
outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */
{
unsigned long startlow, starthigh;
unsigned long endlow, endhigh;
unsigned long count;
rdtsc(startlow,starthigh);
count = 0;
do {
count++;
} while ((inb(0x61) & 0x20) == 0);
rdtsc(endlow,endhigh);
/* Error: ECTCNEVERSET */
if (count <= 1)
goto bad_ctc;
/* 64-bit subtract - gcc just messes up with long longs */
__asm__("subl %2,%0\n\t"
"sbbl %3,%1"
:"=a" (endlow), "=d" (endhigh)
:"g" (startlow), "g" (starthigh),
"0" (endlow), "1" (endhigh));
/* Error: ECPUTOOFAST */
if (endhigh)
goto bad_ctc;
endlow /= 5;
return endlow;
}
/*
* The CTC wasn't reliable: we got a hit on the very first read,
* or the CPU was so fast/slow that the quotient wouldn't fit in
* 32 bits..
*/
bad_ctc:
printf("bad_ctc\n");
return 0;
}
unsigned long currticks(void)
{
static unsigned long clocks_per_tick;
unsigned long clocks_high, clocks_low;
unsigned long currticks;
if (!clocks_per_tick) {
clocks_per_tick = calibrate_tsc();
printf("clocks_per_tick = %d\n", clocks_per_tick);
}
/* Read the Time Stamp Counter */
rdtsc(clocks_low, clocks_high);
/* currticks = clocks / clocks_per_tick; */
__asm__("divl %1"
:"=a" (currticks)
:"r" (clocks_per_tick), "0" (clocks_low), "d" (clocks_high));
return currticks;
}
#endif /* RTC_CURRTICKS */

64
netboot/timer.h Normal file
View file

@ -0,0 +1,64 @@
/* Defines for routines to implement a low-overhead timer for drivers */
/*
* This program is free software; you can redistribute 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 TIMER_H
#define TIMER_H
/* Ports for the 8254 timer chip */
#define TIMER2_PORT 0x42
#define TIMER_MODE_PORT 0x43
/* Meaning of the mode bits */
#define TIMER0_SEL 0x00
#define TIMER1_SEL 0x40
#define TIMER2_SEL 0x80
#define READBACK_SEL 0xC0
#define LATCH_COUNT 0x00
#define LOBYTE_ACCESS 0x10
#define HIBYTE_ACCESS 0x20
#define WORD_ACCESS 0x30
#define MODE0 0x00
#define MODE1 0x02
#define MODE2 0x04
#define MODE3 0x06
#define MODE4 0x08
#define MODE5 0x0A
#define BINARY_COUNT 0x00
#define BCD_COUNT 0x01
/* Timers tick over at this rate */
#define TICKS_PER_MS 1193
/* Parallel Peripheral Controller Port B */
#define PPC_PORTB 0x61
/* Meaning of the port bits */
#define PPCB_T2OUT 0x20 /* Bit 5 */
#define PPCB_SPKR 0x02 /* Bit 1 */
#define PPCB_T2GATE 0x01 /* Bit 0 */
/* Ticks must be between 0 and 65535 (0 == 65536)
because it is a 16 bit counter */
extern void load_timer2(unsigned int ticks);
extern inline int timer2_running(void)
{
return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
}
extern inline void waiton_timer2(unsigned int ticks)
{
load_timer2(ticks);
while ((inb(PPC_PORTB) & PPCB_T2OUT) == 0)
;
}
#endif /* TIMER_H */

3746
netboot/tlan.c Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -688,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=%hX,buf2=%hX",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].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=%hX,buf2=%hX",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. */
@ -705,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=%hX,buf2=%hX",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=%hX,buf2=%hX",i,tp->tx_ring[i-1].buf_addr_1,tp->tx_ring[i-1].buf_addr_2); */
}
int
@ -717,33 +717,24 @@ QueryAuto (int ioaddr)
{
int byMIIIndex;
int MIIReturn;
int FDXFlag;
byMIIIndex = 0x06;
MIIReturn = ReadMII (byMIIIndex, ioaddr);
if ((MIIReturn & 0x01) == 0)
{
FDXFlag = 0;
return FDXFlag;
}
byMIIIndex = 0x05;
MIIReturn = ReadMII (byMIIIndex, ioaddr);
if ((MIIReturn & 0x0140) == 0)
{
FDXFlag = 0;
return FDXFlag;
}
int advertising,mii_reg5;
int negociated;
byMIIIndex = 0x04;
MIIReturn = ReadMII (byMIIIndex, ioaddr);
if ((MIIReturn & 0x0140) == 0)
{
FDXFlag = 0;
return FDXFlag;
}
advertising=MIIReturn;
FDXFlag = 1;
return FDXFlag;
byMIIIndex = 0x05;
MIIReturn = ReadMII (byMIIIndex, ioaddr);
mii_reg5=MIIReturn;
negociated=mii_reg5 & advertising;
if ( (negociated & 0x100) || (negociated & 0x1C0) == 0x40 )
return 1;
else
return 0;
}
@ -867,35 +858,12 @@ struct nic *
rhine_probe (struct nic *nic, unsigned short *probeaddrs,
struct pci_device *pci)
{
unsigned char pci_latency;
unsigned short pci_command;
if (!pci->ioaddr)
return NULL;
nic = rhine_probe1 (nic, pci->ioaddr, 0, -1);
if (nic)
{
/* Get and check the bus-master and latency values. */
pcibios_read_config_word (0, pci->devfn, PCI_COMMAND, &pci_command);
if (!(pci_command & PCI_COMMAND_MASTER))
{
printf (" PCI Master Bit has not been set! Setting...\n");
pci_command |= PCI_COMMAND_MASTER;
pcibios_write_config_word (0, pci->devfn, PCI_COMMAND,
pci_command);
}
pcibios_read_config_byte (0, pci->devfn, PCI_LATENCY_TIMER,
&pci_latency);
if (pci_latency < 10)
{
printf (" PCI latency timer (CFLT) is unreasonably low "
"at %d. Setting to 64 clocks.\n", pci_latency);
pcibios_write_config_byte (0, pci->devfn, PCI_LATENCY_TIMER, 64);
}
else if (rhine_debug > 1)
printf (" PCI latency timer (CFLT) is %#x.\n", pci_latency);
}
adjust_pci_device(pci);
nic->poll = rhine_poll;
nic->transmit = rhine_transmit;
nic->reset = rhine_reset;
@ -917,14 +885,10 @@ rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
if (rhine_debug > 0 && did_version++ == 0)
printf (version);
printf ("IO adress %x ", ioaddr);
/* Perhaps this should be read from the EEPROM? */
for (i = 0; i < 6; i++)
for (i = 0; i < ETH_ALEN; i++)
nic->node_addr[i] = inb (byPAR0 + i);
printf ("Ethernet Address: ");
for (i = 0; i < 5; i++)
printf ("0x%b:", nic->node_addr[i]);
printf ("0x%b\n", nic->node_addr[i]);
printf ("IO address %hX Ethernet Address: %!\n", ioaddr, nic->node_addr);
/* restart MII auto-negotiation */
WriteMII (0, 9, 1, ioaddr);
@ -939,10 +903,27 @@ rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
break;
}
printf ("OK\n");
#if 0
/* JJM : for Debug */
printf("MII : Address %hhX ",inb(ioaddr+0x6c));
{
unsigned char st1,st2,adv1,adv2,l1,l2;
st1=ReadMII(1,ioaddr)>>8;
st2=ReadMII(1,ioaddr)&0xFF;
adv1=ReadMII(4,ioaddr)>>8;
adv2=ReadMII(4,ioaddr)&0xFF;
l1=ReadMII(5,ioaddr)>>8;
l2=ReadMII(5,ioaddr)&0xFF;
printf(" status 0x%hhX%hhX, advertising 0x%hhX%hhX, link 0x%hhX%hhX\n", st1,st2,adv1,adv2,l1,l2);
}
#endif
/* query MII to know LineSpeed,duplex mode */
byMIIvalue = inb (ioaddr + 0x6d);
LineSpeed = byMIIvalue & MIISR_SPEED;
if (LineSpeed == 1)
if (LineSpeed != 0) //JJM
{
printf ("Linespeed=10Mbs");
}
@ -950,6 +931,7 @@ rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
{
printf ("Linespeed=100Mbs");
}
FDXFlag = QueryAuto (ioaddr);
if (FDXFlag == 1)
{
@ -961,6 +943,7 @@ rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
printf (" Halfduplex\n");
}
/* set MII 10 FULL ON */
WriteMII (17, 1, 1, ioaddr);
@ -994,8 +977,14 @@ rhine_probe1 (struct nic *nic, int ioaddr, int chip_id, int options)
static void
rhine_disable (struct nic *nic)
{
struct rhine_private *tp = (struct rhine_private *) nic->priv_data;
int ioaddr = tp->ioaddr;
printf ("rhine disable\n");
/* nothing for the moment */
/* Switch to loopback mode to avoid hardware races. */
writeb(0x60 | 0x01, byTCR);
/* Stop the chip's Tx and Rx processes. */
writew(CR_STOP, byCR0);
}
/**************************************************************************
@ -1013,7 +1002,7 @@ rhine_reset (struct nic *nic)
int rx_bufs_tmp, rx_bufs_tmp1;
int tx_bufs_tmp, tx_bufs_tmp1;
#ifndef USE_INTERNAL_BUFFER
#ifdef USE_LOWMEM_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))
@ -1043,33 +1032,37 @@ rhine_reset (struct nic *nic)
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;
}
/* software reset */
outb (CR1_SFRST, byCR1);
MIIDelay ();
/* printf ("init ring"); */
rhine_init_ring (nic);
/*write TD RD Descriptor to MAC */
@ -1079,9 +1072,6 @@ rhine_reset (struct nic *nic)
/* close IMR */
outw (0x0000, byIMR0);
/* software reset */
outb (CR1_SFRST, byCR1);
MIIDelay ();
/* set TCR RCR threshold */
outb (0x06, byBCR0);
outb (0x00, byBCR1);
@ -1119,7 +1109,7 @@ rhine_poll (struct nic *nic)
}
else if (rxstatus & (RSR_ABNORMAL))
{
printf ("rxerr[%x]\n", rxstatus);
printf ("rxerr[%X]\n", rxstatus);
}
else
good = 1;
@ -1153,16 +1143,16 @@ rhine_transmit (struct nic *nic,
/* Calculate the next Tx descriptor entry. */
entry = tp->cur_tx % TX_RING_SIZE;
memcpy ((void *) tp->tx_buffs[entry], d, ETHER_ADDR_SIZE); /* dst */
memcpy ((void *) tp->tx_buffs[entry] + ETHER_ADDR_SIZE, nic->node_addr, ETHER_ADDR_SIZE); /* src */
memcpy (tp->tx_buffs[entry], d, ETH_ALEN); /* dst */
memcpy (tp->tx_buffs[entry] + ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */
*((char *) tp->tx_buffs[entry] + 12) = t >> 8; /* type */
*((char *) tp->tx_buffs[entry] + 13) = t;
memcpy ((void *) tp->tx_buffs[entry] + ETHER_HDR_SIZE, p, s);
s += ETHER_HDR_SIZE;
while (s < ETH_MIN_PACKET)
*((char *) tp->tx_buffs[entry] + ETHER_HDR_SIZE + (s++)) = 0;
memcpy (tp->tx_buffs[entry] + ETH_HLEN, p, s);
s += ETH_HLEN;
while (s < ETH_ZLEN)
*((char *) tp->tx_buffs[entry] + ETH_HLEN + (s++)) = 0;
tp->tx_ring[entry].tx_ctrl.bits.tx_buf_size = ETHER_HDR_SIZE + s;
tp->tx_ring[entry].tx_ctrl.bits.tx_buf_size = ETH_HLEN + s;
tp->tx_ring[entry].tx_status.bits.own_bit = 1;
@ -1170,14 +1160,14 @@ 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++;

934
netboot/w89c840.c Normal file
View file

@ -0,0 +1,934 @@
/*
* Etherboot - BOOTP/TFTP Bootstrap Program
*
* w89c840.c -- This file implements the winbond-840 driver for etherboot.
*
*/
/*
* Adapted by Igor V. Kovalenko
* -- <garrison@mail.ru>
* OR
* -- <iko@crec.mipt.ru>
* Initial adaptaion stage, including testing, completed 23 August 2000.
*/
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* date version by what
* Written: Aug 20 2000 V0.10 iko Initial revision.
* changes: Aug 22 2000 V0.90 iko Works!
* Aug 23 2000 V0.91 iko Cleanup, posted to etherboot
* maintainer.
* Aug 26 2000 V0.92 iko Fixed Rx ring handling.
* First Linux Kernel (TM)
* successfully loaded using
* this driver.
* Jan 07 2001 V0.93 iko Transmitter timeouts are handled
* using timer2 routines. Proposed
* by Ken Yap to eliminate CPU speed
* dependency.
*
* This is the etherboot driver for cards based on Winbond W89c840F chip.
*
* It was written from skeleton source, with Donald Becker's winbond-840.c
* kernel driver as a guideline. Mostly the w89c840 related definitions
* and the lower level routines have been cut-and-pasted into this source.
*
* Frankly speaking, about 90% of the code was obtained using cut'n'paste
* sequence :) while the remainder appeared while brainstorming
* Linux Kernel 2.4.0-testX source code. Thanks, Donald and Linus!
*
* There was a demand for using this card in a rather large
* remote boot environment at MSKP OVTI Lab of
* Moscow Institute for Physics and Technology (MIPT) -- http://www.mipt.ru/
* so you may count that for motivation.
*
*/
/*
* If you want to see debugging output then define W89C840_DEBUG
*/
/*
#define W89C840_DEBUG
*/
/*
* Keep using IO_OPS for Etherboot driver!
*/
#define USE_IO_OPS
#include "etherboot.h"
#include "nic.h"
#include "pci.h"
#include "cards.h"
#include "timer.h"
static const char *w89c840_version = "diver Version 0.92 - August 27, 2000";
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
/* Linux support functions */
#define virt_to_bus(x) ((unsigned long)x)
#define bus_to_virt(x) ((void *)x)
#define virt_to_le32desc(addr) virt_to_bus(addr)
#define le32desc_to_virt(addr) bus_to_virt(addr)
/*
#define cpu_to_le32(val) (val)
#define le32_to_cpu(val) (val)
*/
/* Operational parameters that are set at compile time. */
/* Keep the ring sizes a power of two for compile efficiency.
The compiler will convert <unsigned>'%'<2^N> into a bit mask.
Making the Tx ring too large decreases the effectiveness of channel
bonding and packet priority.
There are no ill effects from too-large receive rings. */
#define TX_RING_SIZE 2
#define RX_RING_SIZE 2
/* The presumed FIFO size for working around the Tx-FIFO-overflow bug.
To avoid overflowing we don't queue again until we have room for a
full-size packet.
*/
#define TX_FIFO_SIZE (2048)
#define TX_BUG_FIFO_LIMIT (TX_FIFO_SIZE-1514-16)
/* Operational parameters that usually are not changed. */
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT (10*TICKS_PER_MS)
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
/*
* Used to be this much CPU loops on Celeron@400 (?),
* now using real timer and TX_TIMEOUT!
* #define TX_LOOP_COUNT 10000000
*/
#if !defined(__OPTIMIZE__)
#warning You must compile this file with the correct options!
#warning See the last lines of the source file.
#error You must compile this driver with "-O".
#endif
enum chip_capability_flags {CanHaveMII=1, HasBrokenTx=2};
#ifdef USE_IO_OPS
#define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
#else
#define W840_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)
#endif
static u32 driver_flags = CanHaveMII | HasBrokenTx;
/* This driver was written to use PCI memory space, however some x86 systems
work only with I/O space accesses. Pass -DUSE_IO_OPS to use PCI I/O space
accesses instead of memory space. */
#ifdef USE_IO_OPS
#undef readb
#undef readw
#undef readl
#undef writeb
#undef writew
#undef writel
#define readb inb
#define readw inw
#define readl inl
#define writeb outb
#define writew outw
#define writel outl
#endif
/* Offsets to the Command and Status Registers, "CSRs".
While similar to the Tulip, these registers are longword aligned.
Note: It's not useful to define symbolic names for every register bit in
the device. The name can only partially document the semantics and make
the driver longer and more difficult to read.
*/
enum w840_offsets {
PCIBusCfg=0x00, TxStartDemand=0x04, RxStartDemand=0x08,
RxRingPtr=0x0C, TxRingPtr=0x10,
IntrStatus=0x14, NetworkConfig=0x18, IntrEnable=0x1C,
RxMissed=0x20, EECtrl=0x24, MIICtrl=0x24, BootRom=0x28, GPTimer=0x2C,
CurRxDescAddr=0x30, CurRxBufAddr=0x34, /* Debug use */
MulticastFilter0=0x38, MulticastFilter1=0x3C, StationAddr=0x40,
CurTxDescAddr=0x4C, CurTxBufAddr=0x50,
};
/* Bits in the interrupt status/enable registers. */
/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
enum intr_status_bits {
NormalIntr=0x10000, AbnormalIntr=0x8000,
IntrPCIErr=0x2000, TimerInt=0x800,
IntrRxDied=0x100, RxNoBuf=0x80, IntrRxDone=0x40,
TxFIFOUnderflow=0x20, RxErrIntr=0x10,
TxIdle=0x04, IntrTxStopped=0x02, IntrTxDone=0x01,
};
/* Bits in the NetworkConfig register. */
enum rx_mode_bits {
AcceptErr=0x80, AcceptRunt=0x40,
AcceptBroadcast=0x20, AcceptMulticast=0x10,
AcceptAllPhys=0x08, AcceptMyPhys=0x02,
};
enum mii_reg_bits {
MDIO_ShiftClk=0x10000, MDIO_DataIn=0x80000, MDIO_DataOut=0x20000,
MDIO_EnbOutput=0x40000, MDIO_EnbIn = 0x00000,
};
/* The Tulip Rx and Tx buffer descriptors. */
struct w840_rx_desc {
s32 status;
s32 length;
u32 buffer1;
u32 next_desc;
};
struct w840_tx_desc {
s32 status;
s32 length;
u32 buffer1, buffer2; /* We use only buffer 1. */
};
/* Bits in network_desc.status */
enum desc_status_bits {
DescOwn=0x80000000, DescEndRing=0x02000000, DescUseLink=0x01000000,
DescWholePkt=0x60000000, DescStartPkt=0x20000000, DescEndPkt=0x40000000,
DescIntr=0x80000000,
};
#define PRIV_ALIGN 15 /* Required alignment mask */
#define PRIV_ALIGN_BYTES 32
static struct winbond_private
{
/* Descriptor rings first for alignment. */
struct w840_rx_desc rx_ring[RX_RING_SIZE];
struct w840_tx_desc tx_ring[TX_RING_SIZE];
struct net_device *next_module; /* Link for devices of this type. */
void *priv_addr; /* Unaligned address for kfree */
const char *product_name;
/* Frequently used values: keep some adjacent for cache effect. */
int chip_id, drv_flags;
struct pci_dev *pci_dev;
int csr6;
struct w840_rx_desc *rx_head_desc;
unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */
unsigned int rx_buf_sz; /* Based on MTU+slack. */
unsigned int cur_tx, dirty_tx;
int tx_q_bytes;
unsigned int tx_full:1; /* The Tx queue is full. */
/* These values are keep track of the transceiver/media in use. */
unsigned int full_duplex:1; /* Full-duplex operation requested. */
unsigned int duplex_lock:1;
unsigned int medialock:1; /* Do not sense media. */
unsigned int default_port:4; /* Last dev->if_port value. */
/* MII transceiver section. */
int mii_cnt; /* MII device addresses. */
u16 advertising; /* NWay media advertisement */
unsigned char phys[2]; /* MII device addresses. */
} w840private __attribute__ ((aligned (PRIV_ALIGN_BYTES)));
/* NIC specific static variables go here */
static int ioaddr;
static unsigned short eeprom [0x40];
#ifdef USE_LOWMEM_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
static int eeprom_read(long ioaddr, int location);
static int mdio_read(int base_address, int phy_id, int location);
static void mdio_write(int base_address, int phy_id, int location, int value);
static void check_duplex(void);
static void set_rx_mode(void);
static void init_ring(void);
/*
static void wait_long_time(void)
{
printf("Paused - please read output above this line\n");
sleep(3);
}
*/
#if defined W89C840_DEBUG
static void decode_interrupt(u32 intr_status)
{
printf("Interrupt status: ");
#define TRACE_INTR(_intr_) \
if (intr_status & (_intr_)) { printf (" " #_intr_); }
TRACE_INTR(NormalIntr);
TRACE_INTR(AbnormalIntr);
TRACE_INTR(IntrPCIErr);
TRACE_INTR(TimerInt);
TRACE_INTR(IntrRxDied);
TRACE_INTR(RxNoBuf);
TRACE_INTR(IntrRxDone);
TRACE_INTR(TxFIFOUnderflow);
TRACE_INTR(RxErrIntr);
TRACE_INTR(TxIdle);
TRACE_INTR(IntrTxStopped);
TRACE_INTR(IntrTxDone);
printf("\n");
/*sleep(1);*/
}
#endif
/**************************************************************************
w89c840_reset - Reset adapter
***************************************************************************/
static void w89c840_reset(struct nic *nic)
{
int i;
/* Reset the chip to erase previous misconfiguration.
No hold time required! */
writel(0x00000001, ioaddr + PCIBusCfg);
init_ring();
writel(virt_to_bus(w840private.rx_ring), ioaddr + RxRingPtr);
writel(virt_to_bus(w840private.tx_ring), ioaddr + TxRingPtr);
for (i = 0; i < ETH_ALEN; i++)
writeb(nic->node_addr[i], ioaddr + StationAddr + i);
/* Initialize other registers. */
/* Configure the PCI bus bursts and FIFO thresholds.
486: Set 8 longword cache alignment, 8 longword burst.
586: Set 16 longword cache alignment, no burst limit.
Cache alignment bits 15:14 Burst length 13:8
0000 <not allowed> 0000 align to cache 0800 8 longwords
4000 8 longwords 0100 1 longword 1000 16 longwords
8000 16 longwords 0200 2 longwords 2000 32 longwords
C000 32 longwords 0400 4 longwords
Wait the specified 50 PCI cycles after a reset by initializing
Tx and Rx queues and the address filter list. */
writel(0xE010, ioaddr + PCIBusCfg);
writel(0, ioaddr + RxStartDemand);
w840private.csr6 = 0x20022002;
check_duplex();
set_rx_mode();
/* Clear and Enable interrupts by setting the interrupt mask. */
writel(0x1A0F5, ioaddr + IntrStatus);
writel(0x1A0F5, ioaddr + IntrEnable);
#if defined(W89C840_DEBUG)
printf("winbond-840 : Done reset.\n");
#endif
}
static void handle_intr(u32 intr_stat)
{
if ((intr_stat & (NormalIntr|AbnormalIntr)) == 0) {
/* we are polling, do not return now */
/*return 0;*/
} else {
/* Acknowledge all of the current interrupt sources ASAP. */
writel(intr_stat & 0x001ffff, ioaddr + IntrStatus);
}
if (intr_stat & AbnormalIntr) {
/* There was an abnormal interrupt */
printf("\n-=- Abnormal interrupt.\n");
#if defined (W89C840_DEBUG)
decode_interrupt(intr_stat);
#endif
if (intr_stat & RxNoBuf) {
/* There was an interrupt */
printf("-=- <=> No receive buffers available.\n");
writel(0, ioaddr + RxStartDemand);
}
}
}
/**************************************************************************
w89c840_poll - Wait for a frame
***************************************************************************/
static int w89c840_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 */
int packet_received = 0;
u32 intr_status = readl(ioaddr + IntrStatus);
/* handle_intr(intr_status); */ /* -- handled later */
do {
/* Code from netdev_rx(dev) */
int entry = w840private.cur_rx % RX_RING_SIZE;
struct w840_rx_desc *desc = w840private.rx_head_desc;
s32 status = desc->status;
if (status & DescOwn) {
/* DescOwn bit is still set, we should wait for RX to complete */
packet_received = 0;
break;
}
if ((status & 0x38008300) != 0x0300) {
if ((status & 0x38000300) != 0x0300) {
/* Ingore earlier buffers. */
if ((status & 0xffff) != 0x7fff) {
printf("winbond-840 : Oversized Ethernet frame spanned "
"multiple buffers, entry %d status %X !\n",
w840private.cur_rx, status);
}
} else if (status & 0x8000) {
/* There was a fatal error. */
#if defined(W89C840_DEBUG)
printf("winbond-840 : Receive error, Rx status %X :", status);
if (status & 0x0890) {
printf(" RXLEN_ERROR");
}
if (status & 0x004C) {
printf(", FRAME_ERROR");
}
if (status & 0x0002) {
printf(", CRC_ERROR");
}
printf("\n");
#endif
/* Simpy do a reset now... */
w89c840_reset(nic);
packet_received = 0;
break;
}
} else {
/* Omit the four octet CRC from the length. */
int pkt_len = ((status >> 16) & 0x7ff) - 4;
#if defined(W89C840_DEBUG)
printf(" netdev_rx() normal Rx pkt ring %d length %d status %X\n", entry, pkt_len, status);
#endif
nic->packetlen = pkt_len;
/* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */
memcpy(nic->packet, le32desc_to_virt(w840private.rx_ring[entry].buffer1), pkt_len);
packet_received = 1;
/* Release buffer to NIC */
w840private.rx_ring[entry].status = DescOwn;
#if defined(W89C840_DEBUG)
/* You will want this info for the initial debug. */
printf(" Rx data %hhX:%hhX:%hhX:%hhX:%hhX:"
"%hhX %hhX:%hhX:%hhX:%hhX:%hhX:%hhX %hhX%hhX "
"%hhX.%hhX.%hhX.%hhX.\n",
nic->packet[0], nic->packet[1], nic->packet[2], nic->packet[3],
nic->packet[4], nic->packet[5], nic->packet[6], nic->packet[7],
nic->packet[8], nic->packet[9], nic->packet[10],
nic->packet[11], nic->packet[12], nic->packet[13],
nic->packet[14], nic->packet[15], nic->packet[16],
nic->packet[17]);
#endif
}
entry = (++w840private.cur_rx) % RX_RING_SIZE;
w840private.rx_head_desc = &w840private.rx_ring[entry];
} while (0);
if (intr_status & (AbnormalIntr | TxFIFOUnderflow | IntrPCIErr |TimerInt | IntrTxStopped)) {
handle_intr(intr_status);
}
return packet_received;
}
/**************************************************************************
w89c840_transmit - Transmit a frame
***************************************************************************/
static void w89c840_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 */
unsigned entry;
int transmit_status;
/* Caution: the write order is important here, set the field
with the "ownership" bits last. */
/* Fill in our transmit buffer */
entry = w840private.cur_tx % TX_RING_SIZE;
memcpy (tx_packet, d, ETH_ALEN); /* dst */
memcpy (tx_packet + ETH_ALEN, nic->node_addr, ETH_ALEN);/* src */
*((char *) tx_packet + 12) = t >> 8; /* type */
*((char *) tx_packet + 13) = t;
memcpy (tx_packet + ETH_HLEN, p, s);
s += ETH_HLEN;
while (s < ETH_ZLEN)
*((char *) tx_packet + ETH_HLEN + (s++)) = 0;
w840private.tx_ring[entry].buffer1 = virt_to_le32desc(tx_packet);
w840private.tx_ring[entry].length = (DescWholePkt | s);
if (entry >= TX_RING_SIZE-1) /* Wrap ring */
w840private.tx_ring[entry].length |= (DescIntr | DescEndRing);
w840private.tx_ring[entry].status = (DescOwn);
w840private.cur_tx++;
w840private.tx_q_bytes += s;
writel(0, ioaddr + TxStartDemand);
/* Work around horrible bug in the chip by marking the queue as full
when we do not have FIFO room for a maximum sized packet. */
if ((w840private.drv_flags & HasBrokenTx) && w840private.tx_q_bytes > TX_BUG_FIFO_LIMIT) {
/* Actually this is left to help finding error tails later in debugging...
* See Linux kernel driver in winbond-840.c for details.
*/
w840private.tx_full = 1;
}
#if defined(W89C840_DEBUG)
printf("winbond-840 : Transmit frame # %d size %d queued in slot %d.\n", w840private.cur_tx, s, entry);
#endif
/* Now wait for TX to complete. */
transmit_status = w840private.tx_ring[entry].status;
load_timer2(TX_TIMEOUT);
{
u32 intr_stat = 0;
while (1) {
intr_stat = readl(ioaddr + IntrStatus);
#if defined(W89C840_DEBUG)
decode_interrupt(intr_stat);
#endif
if (intr_stat & (NormalIntr | IntrTxDone)) {
while ( (transmit_status & DescOwn) && timer2_running()) {
transmit_status = w840private.tx_ring[entry].status;
}
writel(intr_stat & 0x0001ffff, ioaddr + IntrStatus);
break;
}
}
}
if ((transmit_status & DescOwn) == 0) {
#if defined(W89C840_DEBUG)
printf("winbond-840 : transmission complete after %d wait loop iterations, status %X\n",
TX_LOOP_COUNT - transmit_loop_counter, w840private.tx_ring[entry].status);
#endif
return;
}
/* Transmit timed out... */
printf("winbond-840 : transmission TIMEOUT : status %X\n", w840private.tx_ring[entry].status);
return;
}
/**************************************************************************
w89c840_disable - Turn off ethernet interface
***************************************************************************/
static void w89c840_disable(struct nic *nic)
{
/* Don't know what to do to disable the board. Is this needed at all? */
/* Yes, a live NIC can corrupt the loaded memory later [Ken] */
/* Stop the chip's Tx and Rx processes. */
writel(w840private.csr6 &= ~0x20FA, ioaddr + NetworkConfig);
}
/**************************************************************************
w89c840_probe - Look for an adapter, this routine's visible to the outside
***************************************************************************/
struct nic *w89c840_probe(struct nic *nic, unsigned short *probe_addrs, struct pci_device *p)
{
u16 sum = 0;
int i, j, to;
unsigned short value;
int options;
int promisc;
if (probe_addrs == 0 || probe_addrs[0] == 0)
return 0;
ioaddr = probe_addrs[0]; /* Mask the bit that says "this is an io addr" */
#if defined(W89C840_DEBUG)
printf("winbond-840: PCI bus %hhX device function %hhX: I/O address: %hX\n", p->bus, p->devfn, ioaddr);
#endif
ioaddr = ioaddr & ~3; /* Mask the bit that says "this is an io addr" */
/* if probe_addrs is 0, then routine can use a hardwired default */
/* From Matt Hortman <mbhortman@acpthinclient.com> */
if (p->vendor == PCI_VENDOR_ID_WINBOND2
&& p->dev_id == PCI_DEVICE_ID_WINBOND2_89C840) {
/* detected "Winbond W89c840 Fast Ethernet PCI NIC" */
} else if ( p->vendor == PCI_VENDOR_ID_COMPEX
&& p->dev_id == PCI_DEVICE_ID_COMPEX_RL100ATX) {
/* detected "Compex RL100ATX Fast Ethernet PCI NIC" */
} else {
/* Gee, guess what? They missed again. */
printf("device ID : %X - is not a Compex RL100ATX NIC.\n", p->dev_id);
return 0;
}
printf(" %s\n", w89c840_version);
adjust_pci_device(p);
/* Ok. Got one. Read the eeprom. */
for (j = 0, i = 0; i < 0x40; i++) {
value = eeprom_read(ioaddr, i);
eeprom[i] = value;
sum += value;
}
for (i=0;i<ETH_ALEN;i++) {
nic->node_addr[i] = (eeprom[i/2] >> (8*(i&1))) & 0xff;
}
printf ("Ethernet addr: %!\n", nic->node_addr);
#if defined(W89C840_DEBUG)
printf("winbond-840: EEPROM checksum %hX, got eeprom", sum);
#endif
/* Reset the chip to erase previous misconfiguration.
No hold time required! */
writel(0x00000001, ioaddr + PCIBusCfg);
if (driver_flags & CanHaveMII) {
int phy, phy_idx = 0;
for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
int mii_status = mdio_read(ioaddr, phy, 1);
if (mii_status != 0xffff && mii_status != 0x0000) {
w840private.phys[phy_idx++] = phy;
w840private.advertising = mdio_read(ioaddr, phy, 4);
#if defined(W89C840_DEBUG)
printf("winbond-840 : MII PHY found at address %d, status "
"%X advertising %hX.\n", phy, mii_status, w840private.advertising);
#endif
}
}
w840private.mii_cnt = phy_idx;
if (phy_idx == 0) {
printf("winbond-840 : MII PHY not found -- this device may not operate correctly.\n");
}
}
/* point to NIC specific routines */
nic->reset = w89c840_reset;
nic->poll = w89c840_poll;
nic->transmit = w89c840_transmit;
nic->disable = w89c840_disable;
w89c840_reset(nic);
return nic;
}
/* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. These are
often serial bit streams generated by the host processor.
The example below is for the common 93c46 EEPROM, 64 16 bit words. */
/* Delay between EEPROM clock transitions.
No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need
a delay. Note that pre-2.0.34 kernels had a cache-alignment bug that
made udelay() unreliable.
The old method of using an ISA access as a delay, __SLOW_DOWN_IO__, is
depricated.
*/
#define eeprom_delay(ee_addr) readl(ee_addr)
enum EEPROM_Ctrl_Bits {
EE_ShiftClk=0x02, EE_Write0=0x801, EE_Write1=0x805,
EE_ChipSelect=0x801, EE_DataIn=0x08,
};
/* The EEPROM commands include the alway-set leading bit. */
enum EEPROM_Cmds {
EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
};
static int eeprom_read(long addr, int location)
{
int i;
int retval = 0;
int ee_addr = addr + EECtrl;
int read_cmd = location | EE_ReadCmd;
writel(EE_ChipSelect, ee_addr);
/* Shift the read command bits out. */
for (i = 10; i >= 0; i--) {
short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
writel(dataval, ee_addr);
eeprom_delay(ee_addr);
writel(dataval | EE_ShiftClk, ee_addr);
eeprom_delay(ee_addr);
}
writel(EE_ChipSelect, ee_addr);
for (i = 16; i > 0; i--) {
writel(EE_ChipSelect | EE_ShiftClk, ee_addr);
eeprom_delay(ee_addr);
retval = (retval << 1) | ((readl(ee_addr) & EE_DataIn) ? 1 : 0);
writel(EE_ChipSelect, ee_addr);
eeprom_delay(ee_addr);
}
/* Terminate the EEPROM access. */
writel(0, ee_addr);
return retval;
}
/* MII transceiver control section.
Read and write the MII registers using software-generated serial
MDIO protocol. See the MII specifications or DP83840A data sheet
for details.
The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
met by back-to-back 33Mhz PCI cycles. */
#define mdio_delay(mdio_addr) readl(mdio_addr)
/* Set iff a MII transceiver on any interface requires mdio preamble.
This only set with older tranceivers, so the extra
code size of a per-interface flag is not worthwhile. */
static char mii_preamble_required = 1;
#define MDIO_WRITE0 (MDIO_EnbOutput)
#define MDIO_WRITE1 (MDIO_DataOut | MDIO_EnbOutput)
/* Generate the preamble required for initial synchronization and
a few older transceivers. */
static void mdio_sync(long mdio_addr)
{
int bits = 32;
/* Establish sync by sending at least 32 logic ones. */
while (--bits >= 0) {
writel(MDIO_WRITE1, mdio_addr);
mdio_delay(mdio_addr);
writel(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
}
static int mdio_read(int base_address, int phy_id, int location)
{
long mdio_addr = base_address + MIICtrl;
int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int i, retval = 0;
if (mii_preamble_required)
mdio_sync(mdio_addr);
/* Shift the read command bits out. */
for (i = 15; i >= 0; i--) {
int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
writel(dataval, mdio_addr);
mdio_delay(mdio_addr);
writel(dataval | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
/* Read the two transition, 16 data, and wire-idle bits. */
for (i = 20; i > 0; i--) {
writel(MDIO_EnbIn, mdio_addr);
mdio_delay(mdio_addr);
retval = (retval << 1) | ((readl(mdio_addr) & MDIO_DataIn) ? 1 : 0);
writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
return (retval>>1) & 0xffff;
}
static void mdio_write(int base_address, int phy_id, int location, int value)
{
long mdio_addr = base_address + MIICtrl;
int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
int i;
if (location == 4 && phy_id == w840private.phys[0])
w840private.advertising = value;
if (mii_preamble_required)
mdio_sync(mdio_addr);
/* Shift the command bits out. */
for (i = 31; i >= 0; i--) {
int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
writel(dataval, mdio_addr);
mdio_delay(mdio_addr);
writel(dataval | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
/* Clear out extra bits. */
for (i = 2; i > 0; i--) {
writel(MDIO_EnbIn, mdio_addr);
mdio_delay(mdio_addr);
writel(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
mdio_delay(mdio_addr);
}
return;
}
static void check_duplex(void)
{
int mii_reg5 = mdio_read(ioaddr, w840private.phys[0], 5);
int negotiated = mii_reg5 & w840private.advertising;
int duplex;
if (w840private.duplex_lock || mii_reg5 == 0xffff)
return;
duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
if (w840private.full_duplex != duplex) {
w840private.full_duplex = duplex;
#if defined(W89C840_DEBUG)
printf("winbond-840 : Setting %s-duplex based on MII # %d negotiated capability %X\n",
duplex ? "full" : "half", w840private.phys[0], negotiated);
#endif
w840private.csr6 &= ~0x200;
w840private.csr6 |= duplex ? 0x200 : 0;
}
}
static void set_rx_mode(void)
{
u32 mc_filter[2]; /* Multicast hash filter */
u32 rx_mode;
/* Accept all multicasts from now on. */
memset(mc_filter, 0xff, sizeof(mc_filter));
/*
* Actually, should work OK with multicast enabled. -- iko
*/
/*
* rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
*/
rx_mode = AcceptBroadcast | AcceptMyPhys;
writel(mc_filter[0], ioaddr + MulticastFilter0);
writel(mc_filter[1], ioaddr + MulticastFilter1);
w840private.csr6 &= ~0x00F8;
w840private.csr6 |= rx_mode;
writel(w840private.csr6, ioaddr + NetworkConfig);
#if defined(W89C840_DEBUG)
printf("winbond-840 : Done setting RX mode.\n");
#endif
}
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void init_ring(void)
{
int i;
char * p;
w840private.tx_full = 0;
w840private.tx_q_bytes = w840private.cur_rx = w840private.cur_tx = 0;
w840private.dirty_rx = w840private.dirty_tx = 0;
w840private.rx_buf_sz = PKT_BUF_SZ;
w840private.rx_head_desc = &w840private.rx_ring[0];
/* Initial all Rx descriptors. Fill in the Rx buffers. */
p = &rx_packet[0];
for (i = 0; i < RX_RING_SIZE; i++) {
w840private.rx_ring[i].length = w840private.rx_buf_sz;
w840private.rx_ring[i].status = 0;
w840private.rx_ring[i].next_desc = virt_to_le32desc(&w840private.rx_ring[i+1]);
w840private.rx_ring[i].buffer1 = virt_to_le32desc(p + (PKT_BUF_SZ * i));
w840private.rx_ring[i].status = DescOwn | DescIntr;
}
/* Mark the last entry as wrapping the ring. */
w840private.rx_ring[i-1].length |= DescEndRing;
w840private.rx_ring[i-1].next_desc = virt_to_le32desc(&w840private.rx_ring[0]);
w840private.dirty_rx = (unsigned int)(i - RX_RING_SIZE);
for (i = 0; i < TX_RING_SIZE; i++) {
w840private.tx_ring[i].status = 0;
}
return;
}

View file

@ -28,6 +28,7 @@
#include <filesys.h>
#ifdef SUPPORT_NETBOOT
# define GRUB 1
# include <etherboot.h>
#endif
@ -242,6 +243,11 @@ boot_func (char *arg, int flags)
not KERNEL_TYPE_NONE. Is this assumption is bad? */
if (kernel_type != KERNEL_TYPE_NONE)
unset_int15_handler ();
#ifdef SUPPORT_NETBOOT
/* Shut down the networking. */
cleanup_net ();
#endif
switch (kernel_type)
{

View file

@ -21,6 +21,7 @@
#include <shared.h>
#ifdef SUPPORT_DISKLESS
# define GRUB 1
# include <etherboot.h>
#endif

View file

@ -21,6 +21,7 @@
#include <shared.h>
#ifdef SUPPORT_DISKLESS
# define GRUB 1
# include <etherboot.h>
#endif