]> Zhao Yanbai Git Server - minix.git/commitdiff
rtl8169 driver contributed by Jaswinder Singh Rajput.
authorBen Gras <ben@minix3.org>
Wed, 2 Dec 2009 15:59:42 +0000 (15:59 +0000)
committerBen Gras <ben@minix3.org>
Wed, 2 Dec 2009 15:59:42 +0000 (15:59 +0000)
drivers/Makefile
drivers/pci/pci_table.c
drivers/rtl8169/Makefile [new file with mode: 0644]
drivers/rtl8169/rtl8169.c [new file with mode: 0644]
drivers/rtl8169/rtl8169.h [new file with mode: 0644]
etc/drivers.conf
etc/usr/rc

index c121e6b0e2b2f02e08b36cb3d11f737ef1fd543d..4e3156125c4be60bb9d0972db57766a848565983 100644 (file)
@@ -23,6 +23,7 @@ all install depend clean:
        cd ./floppy && $(MAKE) $@
        cd ./printer && $(MAKE) $@
        cd ./rtl8139 && $(MAKE) $@
+       cd ./rtl8169 && $(MAKE) $@
        cd ./orinoco && $(MAKE) $@
        cd ./fxp && $(MAKE) $@
        cd ./dpeth && $(MAKE) $@
index c38a23cc41ac7d91f2d8ab3f7f5cc353c7abfd44..3c401bab96596c006b12997aae7af93e67be9be6 100644 (file)
@@ -37,8 +37,13 @@ struct pci_vendor pci_vendor_table[]=
        { 0x10EC, "Realtek" },
        { 0x1106, "VIA" },
        { 0x110A, "Siemens Nixdorf AG" },
+       { 0x1186, "D-Link" },
        { 0x125D, "ESS Technology" },
+       { 0x1259, "Allied Telesyn International" },
        { 0x1274, "Ensoniq" },
+       { 0x1385, "Netgear" },
+       { 0x16ec, "US Robotics" },
+       { 0x1737, "Linksys" },
        { 0x5333, "S3" },
        { 0x8086, "Intel" },
        { 0x9004, "Adaptec" },
@@ -83,7 +88,10 @@ struct pci_device pci_device_table[]=
        { 0x10DE, 0x0020, "nVidia Riva TnT [NV04]" },
        { 0x10DE, 0x0110, "nVidia GeForce2 MX [NV11]" },
        { 0x10EC, 0x8029, "Realtek RTL8029" },
+       { 0x10EC, 0x8129, "Realtek RTL8129" },
        { 0x10EC, 0x8139, "Realtek RTL8139" },
+       { 0x10EC, 0x8167, "Realtek RTL8169/8110 Family Gigabit NIC" },
+       { 0x10EC, 0x8169, "Realtek RTL8169" },
        { 0x1106, 0x0305, "VIA VT8363/8365 [KT133/KM133]" },
        { 0x1106, 0x0571, "VIA IDE controller" },
        { 0x1106, 0x0686, "VIA VT82C686 (Apollo South Bridge)" },
@@ -107,10 +115,15 @@ struct pci_device pci_device_table[]=
        { 0x1106, 0xB188, "VT8237 PCI bridge" },
        { 0x110A, 0x0005, "Siemens Nixdorf Tulip Cntlr., Power Management" },
        { 0x1186, 0x1300, "D-Link RTL8139" },
+       { 0x1186, 0x4300, "D-Link Gigabit adapter" },
+       { 0x1259, 0xc107, "Allied Telesyn International Gigabit Ethernet Adapter" },
        { 0x125D, 0x1969, "ESS ES1969 Solo-1 Audiodrive" },
        { 0x1274, 0x1371, "Ensoniq ES1371 [AudioPCI-97]" },
        { 0x1274, 0x5000, "Ensoniq ES1370" },
        { 0x1274, 0x5880, "Ensoniq CT5880 [AudioPCI]" },
+       { 0x1385, 0x8169, "Netgear Gigabit Ethernet Adapter" },
+       { 0x16ec, 0x0116, "US Robotics Realtek 8169S chip" },
+       { 0x1737, 0x1032, "Linksys Instant Gigabit Desktop Network Interface" },
        { 0x5333, 0x8811, "S3 86c764/765 [Trio32/64/64V+]" },
        { 0x5333, 0x883d, "S3 Virge/VX" },
        { 0x5333, 0x88d0, "S3 Vision 964 vers 0" },
diff --git a/drivers/rtl8169/Makefile b/drivers/rtl8169/Makefile
new file mode 100644 (file)
index 0000000..0d9403a
--- /dev/null
@@ -0,0 +1,41 @@
+# Makefile for the Realtek RTL8169 ethernet driver (RTL8169)
+DRIVER = rtl8169
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+# programs, flags, etc.
+MAKE = exec make
+CC =   exec cc
+CFLAGS = -I$i $(CPROFILE)
+LDFLAGS = -i
+LIBS = -lsys -ltimers
+
+OBJ = rtl8169.o
+
+# build local binary
+all build:     $(DRIVER)
+$(DRIVER):     $(OBJ)
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+       install -S 64kw $(DRIVER)
+
+# install with other drivers
+install:       /usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):   $(DRIVER)
+       install -o root -cs $? $@
+
+# clean up local files
+clean:
+       rm -f $(DRIVER) *.o *.bak
+
+depend:
+       mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
diff --git a/drivers/rtl8169/rtl8169.c b/drivers/rtl8169/rtl8169.c
new file mode 100644 (file)
index 0000000..e3de8e3
--- /dev/null
@@ -0,0 +1,2136 @@
+/*
+ * rtl8169.c
+ *
+ * This file contains a ethernet device driver for Realtek rtl8169 based
+ * ethernet cards.
+ *
+ */
+
+#include "../drivers.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <minix/com.h>
+#include <minix/ds.h>
+#include <minix/keymap.h>
+#include <minix/syslib.h>
+#include <minix/type.h>
+#include <minix/sysutil.h>
+#include <minix/endpoint.h>
+#include <timers.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <ibm/pci.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/ioc_memory.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+
+#define tmra_ut                        timer_t
+#define tmra_inittimer(tp)     tmr_inittimer(tp)
+#define Proc_number(p)         proc_number(p)
+#define debug                  1
+#define printW()               ((void)0)
+
+#define VERBOSE                0               /* display message during init */
+
+#include "rtl8169.h"
+
+#define RE_PORT_NR     1               /* Minix */
+
+#define IOVEC_NR       16              /* I/O vectors are handled IOVEC_NR entries at a time. */
+
+#define RE_DTCC_VALUE  600             /* DTCC Update after every 10 minutes */
+
+#define RX_CONFIG_MASK 0xff7e1880      /* Clears the bits supported by chip */
+
+#define RE_INTR_MASK   (RL_IMR_TDU | RL_IMR_FOVW | RL_IMR_PUN | RL_IMR_RDU | RL_IMR_TER | RL_IMR_TOK | RL_IMR_RER | RL_IMR_ROK)
+
+#define RL_ENVVAR      "RTLETH"        /* Configuration */
+
+PRIVATE struct pcitab
+{
+       u16_t vid;
+       u16_t did;
+       int checkclass;
+} pcitab[] =
+{
+       { 0x10ec, 0x8129, 0 },  /* Realtek RTL8129 */
+       { 0x10ec, 0x8167, 0 },  /* Realtek RTL8169/8110 Family Gigabit NIC */
+       { 0x10ec, 0x8169, 0 },  /* Realtek RTL8169 */
+
+       { 0x1186, 0x4300, 0 },  /* D-Link DGE-528T Gigabit adaptor */
+
+       { 0x1259, 0xc107, 0 },  /* Allied Telesyn International Gigabit Ethernet Adapter */
+
+       { 0x1385, 0x8169, 0 },  /* Netgear Gigabit Ethernet Adapter */
+
+       { 0x16ec, 0x0116, 0 },  /* US Robotics Realtek 8169S chip */
+
+       { 0x1737, 0x1032, 0 },  /* Linksys Instant Gigabit Desktop Network Interface */
+
+       { 0x0000, 0x0000, 0 }
+};
+
+typedef struct re_desc
+{
+       u32_t status;           /* command/status */
+       u32_t vlan;             /* VLAN */
+       u32_t addr_low;         /* low 32-bits of physical buffer address */
+       u32_t addr_high;        /* high 32-bits of physical buffer address */
+} re_desc;
+
+typedef struct re_dtcc
+{
+       u32_t   TxOk_low;       /* low 32-bits of Tx Ok packets */
+       u32_t   TxOk_high;      /* high 32-bits of Tx Ok packets */
+       u32_t   RxOk_low;       /* low 32-bits of Rx Ok packets */
+       u32_t   RxOk_high;      /* high 32-bits of Rx Ok packets */
+       u32_t   TxEr_low;       /* low 32-bits of Tx errors */
+       u32_t   TxEr_high;      /* high 32-bits of Tx errors */
+       u32_t   RxEr;           /* Rx errors */
+       u16_t   MissPkt;        /* Missed packets */
+       u16_t   FAE;            /* Frame Aignment Error packets (MII mode only) */
+       u32_t   Tx1Col;         /* Tx Ok packets with only 1 collision happened before Tx Ok */
+       u32_t   TxMCol;         /* Tx Ok packets with > 1 and < 16 collisions happened before Tx Ok */
+       u32_t   RxOkPhy_low;    /* low 32-bits of Rx Ok packets with physical addr destination ID */
+       u32_t   RxOkPhy_high;   /* high 32-bits of Rx Ok packets with physical addr destination ID */
+       u32_t   RxOkBrd_low;    /* low 32-bits of Rx Ok packets with broadcast destination ID */
+       u32_t   RxOkBrd_high;   /* high 32-bits of Rx Ok packets with broadcast destination ID */
+       u32_t   RxOkMul;        /* Rx Ok Packets with multicast destination ID */
+       u16_t   TxAbt;          /* Tx abort packets */
+       u16_t   TxUndrn;        /* Tx underrun packets */
+} re_dtcc;
+
+typedef struct re {
+       port_t re_base_port;
+       int re_irq;
+       int re_mode;
+       int re_flags;
+       endpoint_t re_client;
+       int re_link_up;
+       int re_got_int;
+       int re_send_int;
+       int re_report_link;
+       int re_need_reset;
+       int re_tx_alive;
+       int setup;
+       u32_t re_mac;
+       char *re_model;
+
+       /* Rx */
+       int re_rx_head;
+       struct {
+               int ret_busy;
+               phys_bytes ret_buf;
+               char *v_ret_buf;
+       } re_rx[N_RX_DESC];
+
+       vir_bytes re_read_s;
+       re_desc *re_rx_desc;    /* Rx descriptor buffer */
+       phys_bytes p_rx_desc;   /* Rx descriptor buffer physical */
+
+       /* Tx */
+       int re_tx_head;
+       struct {
+               int ret_busy;
+               phys_bytes ret_buf;
+               char *v_ret_buf;
+       } re_tx[N_TX_DESC];
+       re_desc *re_tx_desc;    /* Tx descriptor buffer */
+       phys_bytes p_tx_desc;   /* Tx descriptor buffer physical */
+
+       /* PCI related */
+       int re_seen;            /* TRUE iff device available */
+       u8_t re_pcibus;
+       u8_t re_pcidev;
+       u8_t re_pcifunc;
+
+       /* 'large' items */
+       int re_hook_id;         /* IRQ hook id at kernel */
+       eth_stat_t re_stat;
+       phys_bytes dtcc_buf;    /* Dump Tally Counter buffer physical */
+       re_dtcc *v_dtcc_buf;    /* Dump Tally Counter buffer */
+       u32_t dtcc_counter;     /* DTCC update counter */
+       ether_addr_t re_address;
+       message re_rx_mess;
+       message re_tx_mess;
+       char re_name[sizeof("rtl8169#n")];
+       iovec_t re_iovec[IOVEC_NR];
+       iovec_s_t re_iovec_s[IOVEC_NR];
+       u32_t interrupts;
+}
+re_t;
+
+#define REM_DISABLED   0x0
+#define REM_ENABLED    0x1
+
+#define REF_PACK_SENT  0x001
+#define REF_PACK_RECV  0x002
+#define REF_SEND_AVAIL 0x004
+#define REF_READING    0x010
+#define REF_EMPTY      0x000
+#define REF_PROMISC    0x040
+#define REF_MULTI      0x080
+#define REF_BROAD      0x100
+#define REF_ENABLED    0x200
+
+static re_t re_table[RE_PORT_NR];
+
+static u16_t eth_ign_proto;
+static tmra_ut rl_watchdog;
+
+FORWARD _PROTOTYPE(unsigned my_inb, (U16_t port));
+FORWARD _PROTOTYPE(unsigned my_inw, (U16_t port));
+FORWARD _PROTOTYPE(unsigned my_inl, (U16_t port));
+static unsigned my_inb(U16_t port)
+{
+       u32_t value;
+       int s;
+       if ((s = sys_inb(port, &value)) != OK)
+               printf("RTL8169: warning, sys_inb failed: %d\n", s);
+       return value;
+}
+static unsigned my_inw(U16_t port)
+{
+       u32_t value;
+       int s;
+       if ((s = sys_inw(port, &value)) != OK)
+               printf("RTL8169: warning, sys_inw failed: %d\n", s);
+       return value;
+}
+static unsigned my_inl(U16_t port)
+{
+       U32_t value;
+       int s;
+       if ((s = sys_inl(port, &value)) != OK)
+               printf("RTL8169: warning, sys_inl failed: %d\n", s);
+       return value;
+}
+#define rl_inb(port, offset)   (my_inb((port) + (offset)))
+#define rl_inw(port, offset)   (my_inw((port) + (offset)))
+#define rl_inl(port, offset)   (my_inl((port) + (offset)))
+
+FORWARD _PROTOTYPE(void my_outb, (U16_t port, U8_t value));
+FORWARD _PROTOTYPE(void my_outw, (U16_t port, U16_t value));
+FORWARD _PROTOTYPE(void my_outl, (U16_t port, U32_t value));
+static void my_outb(U16_t port, U8_t value)
+{
+       int s;
+
+       if ((s = sys_outb(port, value)) != OK)
+               printf("RTL8169: warning, sys_outb failed: %d\n", s);
+}
+static void my_outw(U16_t port, U16_t value)
+{
+       int s;
+
+       if ((s = sys_outw(port, value)) != OK)
+               printf("RTL8169: warning, sys_outw failed: %d\n", s);
+}
+static void my_outl(U16_t port, U32_t value)
+{
+       int s;
+
+       if ((s = sys_outl(port, value)) != OK)
+               printf("RTL8169: warning, sys_outl failed: %d\n", s);
+}
+#define rl_outb(port, offset, value)   (my_outb((port) + (offset), (value)))
+#define rl_outw(port, offset, value)   (my_outw((port) + (offset), (value)))
+#define rl_outl(port, offset, value)   (my_outl((port) + (offset), (value)))
+
+_PROTOTYPE( static void rl_init, (message *mp)                         );
+_PROTOTYPE( static void rl_pci_conf, (void)                            );
+_PROTOTYPE( static int rl_probe, (re_t *rep)                           );
+_PROTOTYPE( static void rl_conf_hw, (re_t *rep)                                );
+_PROTOTYPE( static void rl_init_buf, (re_t *rep)                       );
+_PROTOTYPE( static void rl_init_hw, (re_t *rep)                                );
+_PROTOTYPE( static void rl_reset_hw, (re_t *rep)                       );
+_PROTOTYPE( static void rl_confaddr, (re_t *rep)                       );
+_PROTOTYPE( static void rl_rec_mode, (re_t *rep)                       );
+_PROTOTYPE( static void rl_readv_s, (message *mp, int from_int)        );
+_PROTOTYPE( static void rl_writev_s, (message *mp, int from_int)       );
+_PROTOTYPE( static void rl_check_ints, (re_t *rep)                     );
+_PROTOTYPE( static void rl_report_link, (re_t *rep)                    );
+_PROTOTYPE( static void rl_do_reset, (re_t *rep)                       );
+_PROTOTYPE( static void rl_getstat, (message *mp)                      );
+_PROTOTYPE( static void rl_getstat_s, (message *mp)                    );
+_PROTOTYPE( static void rl_getname, (message *mp)                      );
+_PROTOTYPE( static void reply, (re_t *rep, int err, int may_block)     );
+_PROTOTYPE( static void mess_reply, (message *req, message *reply)     );
+_PROTOTYPE( static void rtl8169_stop, (void)                           );
+_PROTOTYPE( static void check_int_events, (void)                       );
+_PROTOTYPE( static void do_hard_int, (void)                            );
+_PROTOTYPE( static void rtl8169_dump, (void)                           );
+_PROTOTYPE( static void dump_phy, (re_t *rep)                          );
+_PROTOTYPE( static int rl_handler, (re_t *rep)                         );
+_PROTOTYPE( static void rl_watchdog_f, (timer_t *tp)                   );
+
+/*
+ * The message used in the main loop is made global, so that rl_watchdog_f()
+ * can change its message type to fake an interrupt message.
+ */
+PRIVATE message m;
+PRIVATE int int_event_check;           /* set to TRUE if events arrived */
+
+static char *progname;
+u32_t system_hz;
+
+/*===========================================================================*
+ *                             main                                         *
+ *===========================================================================*/
+int main(int argc, char *argv[])
+{
+       u32_t inet_proc_nr;
+       int r;
+       re_t *rep;
+       long v;
+
+       system_hz = sys_hz();
+
+       (progname = strrchr(argv[0], '/')) ? progname++ : (progname = argv[0]);
+
+       env_setargs(argc, argv);
+
+       v = 0;
+       (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
+       eth_ign_proto = htons((u16_t) v);
+
+       /* Claim buffer memory now under Minix, before MM takes it all. */
+       for (rep = &re_table[0]; rep < re_table + RE_PORT_NR; rep++)
+               rl_init_buf(rep);
+
+       /*
+        * Try to notify INET that we are present (again). If INET cannot
+        * be found, assume this is the first time we started and INET is
+        * not yet alive.
+        */
+#if 0
+       r = ds_retrieve_u32("inet", &inet_proc_nr);
+       if (r == OK)
+               notify(inet_proc_nr);
+       else if (r != ESRCH)
+               printf("rtl8169: ds_retrieve_u32 failed for 'inet': %d\n", r);
+#endif
+       while (TRUE) {
+               if ((r = receive(ANY, &m)) != OK)
+                       panic("rtl8169", "receive failed", r);
+
+               if (is_notify(m.m_type)) {
+                       switch (_ENDPOINT_P(m.m_source)) {
+                       case RS_PROC_NR:
+                               notify(m.m_source);
+                               break;
+                       case CLOCK:
+                               /*
+                                * Under MINIX, synchronous alarms are used
+                                * instead of watchdog functions.
+                                * The approach is very different: MINIX VMD
+                                * timeouts are handled within the kernel
+                                * (the watchdog is executed by CLOCK), and
+                                * notify() the driver in some cases. MINIX
+                                * timeouts result in a SYN_ALARM message to
+                                * the driver and thus are handled where they
+                                * should be handled. Locally, watchdog
+                                * functions are used again.
+                                */
+                               rl_watchdog_f(NULL);
+                               break;
+                       case HARDWARE:
+                               do_hard_int();
+                               if (int_event_check) {
+                                       check_int_events();
+                               }
+                               break ;
+                       case PM_PROC_NR:
+                       {
+                               sigset_t set;
+
+                               if (getsigset(&set) != 0) break;
+
+                               if (sigismember(&set, SIGTERM))
+                                       rtl8169_stop();
+
+                               break;
+                       }
+                       default:
+                               panic("rtl8169", "illegal notify from",
+                                       m.m_type);
+                       }
+
+                       /* done, get nwe message */
+                       continue;
+               }
+
+               switch (m.m_type) {
+               case DL_WRITEV_S:       rl_writev_s(&m, FALSE);  break;
+               case DL_READV_S:        rl_readv_s(&m, FALSE);   break;
+               case DL_CONF:           rl_init(&m);             break;
+               case DL_GETSTAT:        rl_getstat(&m);          break;
+               case DL_GETSTAT_S:      rl_getstat_s(&m);        break;
+               case DL_GETNAME:        rl_getname(&m);          break;
+               default:
+                       panic("rtl8169", "illegal message", m.m_type);
+               }
+       }
+}
+
+static void mdio_write(U16_t port, int regaddr, int value)
+{
+       int i;
+
+       rl_outl(port,  RL_PHYAR, 0x80000000 | (regaddr & 0x1F) << 16 | (value & 0xFFFF));
+
+       for (i = 20; i > 0; i--) {
+               /*
+                * Check if the RTL8169 has completed writing to the specified
+                * MII register
+                */
+               if (!(rl_inl(port, RL_PHYAR) & 0x80000000))
+                       break;
+               else
+                       micro_delay(50);
+       }
+}
+
+static int mdio_read(U16_t port, int regaddr)
+{
+       int i, value = -1;
+
+       rl_outl(port, RL_PHYAR, (regaddr & 0x1F) << 16);
+
+       for (i = 20; i > 0; i--) {
+               /*
+                * Check if the RTL8169 has completed retrieving data from
+                * the specified MII register
+                */
+               if (rl_inl(port, RL_PHYAR) & 0x80000000) {
+                       value = (int)(rl_inl(port, RL_PHYAR) & 0xFFFF);
+                       break;
+               } else
+                       micro_delay(50);
+       }
+       return value;
+}
+
+/*===========================================================================*
+ *                             check_int_events                             *
+ *===========================================================================*/
+static void check_int_events(void)
+{
+       int i;
+       re_t *rep;
+
+       for (i = 0, rep = &re_table[0]; i < RE_PORT_NR; i++, rep++) {
+               if (rep->re_mode != REM_ENABLED)
+                       continue;
+               if (!rep->re_got_int)
+                       continue;
+               rep->re_got_int = 0;
+               assert(rep->re_flags & REF_ENABLED);
+               rl_check_ints(rep);
+       }
+}
+
+/*===========================================================================*
+ *                             rtl8169_stop                                 *
+ *===========================================================================*/
+static void rtl8169_stop()
+{
+       int i;
+       re_t *rep;
+
+       for (i = 0, rep = &re_table[0]; i < RE_PORT_NR; i++, rep++) {
+               if (rep->re_mode != REM_ENABLED)
+                       continue;
+               rl_outb(rep->re_base_port, RL_CR, 0);
+       }
+
+       exit(0);
+}
+
+static void rtl8169_update_stat(re_t *rep)
+{
+       port_t port;
+       int i;
+
+       port = rep->re_base_port;
+
+       /* Fetch Missed Packets */
+       rep->re_stat.ets_missedP += rl_inw(port, RL_MPC);
+       rl_outw(port, RL_MPC, 0x00);
+
+       /* Dump Tally Counter Command */
+       rl_outl(port, RL_DTCCR_HI, 0);          /* 64 bits */
+       rl_outl(port, RL_DTCCR_LO, rep->dtcc_buf | RL_DTCCR_CMD);
+       for (i = 0; i < 1000; i++) {
+               if (!(rl_inl(port, RL_DTCCR_LO) & RL_DTCCR_CMD))
+                       break;
+               micro_delay(10);
+       }
+
+       /* Update counters */
+       rep->re_stat.ets_frameAll = rep->v_dtcc_buf->FAE;
+       rep->re_stat.ets_transDef = rep->v_dtcc_buf->TxUndrn;
+       rep->re_stat.ets_transAb = rep->v_dtcc_buf->TxAbt;
+       rep->re_stat.ets_collision =
+               rep->v_dtcc_buf->Tx1Col + rep->v_dtcc_buf->TxMCol;
+}
+
+/*===========================================================================*
+ *                             rtl8169_dump                                 *
+ *===========================================================================*/
+static void rtl8169_dump(void)
+{
+       re_dtcc *dtcc;
+       re_t *rep;
+       int i;
+
+       printf("\n");
+       for (i = 0, rep = &re_table[0]; i < RE_PORT_NR; i++, rep++) {
+               if (rep->re_mode == REM_DISABLED)
+                       printf("Realtek RTL 8169 port %d is disabled\n", i);
+
+               if (rep->re_mode != REM_ENABLED)
+                       continue;
+
+               rtl8169_update_stat(rep);
+
+               printf("Realtek RTL 8169 statistics of port %d:\n", i);
+
+               printf("recvErr    :%8ld\t", rep->re_stat.ets_recvErr);
+               printf("sendErr    :%8ld\t", rep->re_stat.ets_sendErr);
+               printf("OVW        :%8ld\n", rep->re_stat.ets_OVW);
+
+               printf("CRCerr     :%8ld\t", rep->re_stat.ets_CRCerr);
+               printf("frameAll   :%8ld\t", rep->re_stat.ets_frameAll);
+               printf("missedP    :%8ld\n", rep->re_stat.ets_missedP);
+
+               printf("packetR    :%8ld\t", rep->re_stat.ets_packetR);
+               printf("packetT    :%8ld\t", rep->re_stat.ets_packetT);
+               printf("transDef   :%8ld\n", rep->re_stat.ets_transDef);
+
+               printf("collision  :%8ld\t", rep->re_stat.ets_collision);
+               printf("transAb    :%8ld\t", rep->re_stat.ets_transAb);
+               printf("carrSense  :%8ld\n", rep->re_stat.ets_carrSense);
+
+               printf("fifoUnder  :%8ld\t", rep->re_stat.ets_fifoUnder);
+               printf("fifoOver   :%8ld\t", rep->re_stat.ets_fifoOver);
+               printf("OWC        :%8ld\n", rep->re_stat.ets_OWC);
+               printf("interrupts :%8lu\n", rep->interrupts);
+
+               printf("\nRealtek RTL 8169 Tally Counters:\n");
+
+               dtcc = rep->v_dtcc_buf;
+
+               if (dtcc->TxOk_high)
+                       printf("TxOk       :%8ld%08ld\t", dtcc->TxOk_high, dtcc->TxOk_low);
+               else
+                       printf("TxOk       :%16lu\t", dtcc->TxOk_low);
+
+               if (dtcc->RxOk_high)
+                       printf("RxOk       :%8ld%08ld\n", dtcc->RxOk_high, dtcc->RxOk_low);
+               else
+                       printf("RxOk       :%16lu\n", dtcc->RxOk_low);
+
+               if (dtcc->TxEr_high)
+                       printf("TxEr       :%8ld%08ld\t", dtcc->TxEr_high, dtcc->TxEr_low);
+               else
+                       printf("TxEr       :%16ld\t", dtcc->TxEr_low);
+
+               printf("RxEr       :%16ld\n", dtcc->RxEr);
+
+               printf("Tx1Col     :%16ld\t", dtcc->Tx1Col);
+               printf("TxMCol     :%16ld\n", dtcc->TxMCol);
+
+               if (dtcc->RxOkPhy_high)
+                       printf("RxOkPhy    :%8ld%08ld\t", dtcc->RxOkPhy_high, dtcc->RxOkPhy_low);
+               else
+                       printf("RxOkPhy    :%16ld\t", dtcc->RxOkPhy_low);
+
+               if (dtcc->RxOkBrd_high)
+                       printf("RxOkBrd    :%8ld%08ld\n", dtcc->RxOkBrd_high, dtcc->RxOkBrd_low);
+               else
+                       printf("RxOkBrd    :%16ld\n", dtcc->RxOkBrd_low);
+
+               printf("RxOkMul    :%16ld\t", dtcc->RxOkMul);
+               printf("MissPkt    :%16d\n", dtcc->MissPkt);
+
+               printf("\nRealtek RTL 8169 Miscellaneous Info:\n");
+
+               printf("re_flags   :      0x%08x\n", rep->re_flags);
+               printf("tx_head    :%8d  busy %d\t",
+                       rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
+       }
+}
+
+/*===========================================================================*
+ *                             do_init                                      *
+ *===========================================================================*/
+static void rl_init(mp)
+message *mp;
+{
+       static int first_time = 1;
+
+       int port;
+       re_t *rep;
+       message reply_mess;
+
+       if (first_time) {
+               first_time = 0;
+               rl_pci_conf();  /* Configure PCI devices. */
+
+               tmra_inittimer(&rl_watchdog);
+               /* Use a synchronous alarm instead of a watchdog timer. */
+               sys_setalarm(system_hz, 0);
+       }
+
+       port = mp->DL_PORT;
+       if (port < 0 || port >= RE_PORT_NR) {
+               reply_mess.m_type = DL_CONF_REPLY;
+               reply_mess.m3_i1 = ENXIO;
+               mess_reply(mp, &reply_mess);
+               return;
+       }
+       rep = &re_table[port];
+       if (rep->re_mode == REM_DISABLED) {
+               /* This is the default, try to (re)locate the device. */
+               rl_conf_hw(rep);
+               if (rep->re_mode == REM_DISABLED) {
+                       /* Probe failed, or the device is configured off. */
+                       reply_mess.m_type = DL_CONF_REPLY;
+                       reply_mess.m3_i1 = ENXIO;
+                       mess_reply(mp, &reply_mess);
+                       return;
+               }
+               if (rep->re_mode == REM_ENABLED)
+                       rl_init_hw(rep);
+       }
+
+       assert(rep->re_mode == REM_ENABLED);
+       assert(rep->re_flags & REF_ENABLED);
+
+       rep->re_flags &= ~(REF_PROMISC | REF_MULTI | REF_BROAD);
+
+       if (mp->DL_MODE & DL_PROMISC_REQ)
+               rep->re_flags |= REF_PROMISC;
+       if (mp->DL_MODE & DL_MULTI_REQ)
+               rep->re_flags |= REF_MULTI;
+       if (mp->DL_MODE & DL_BROAD_REQ)
+               rep->re_flags |= REF_BROAD;
+
+       rep->re_client = mp->m_source;
+       rl_rec_mode(rep);
+
+       reply_mess.m_type = DL_CONF_REPLY;
+       reply_mess.m3_i1 = mp->DL_PORT;
+       reply_mess.m3_i2 = RE_PORT_NR;
+       *(ether_addr_t *) reply_mess.m3_ca1 = rep->re_address;
+
+       mess_reply(mp, &reply_mess);
+}
+
+/*===========================================================================*
+ *                             rl_pci_conf                                  *
+ *===========================================================================*/
+static void rl_pci_conf()
+{
+       int i, h;
+       re_t *rep;
+       static char envvar[] = RL_ENVVAR "#";
+       static char envfmt[] = "*:d.d.d";
+       static char val[128];
+       long v;
+
+       for (i = 0, rep = re_table; i < RE_PORT_NR; i++, rep++) {
+               strcpy(rep->re_name, "rtl8169#0");
+               rep->re_name[8] += i;
+               rep->re_seen = FALSE;
+               envvar[sizeof(RL_ENVVAR)-1] = '0' + i;
+               if (0 == env_get_param(envvar, val, sizeof(val)) &&
+                       !env_prefix(envvar, "pci"))
+               {
+                       env_panic(envvar);
+               }
+               v = 0;
+               (void) env_parse(envvar, envfmt, 1, &v, 0, 255);
+               rep->re_pcibus = v;
+               v = 0;
+               (void) env_parse(envvar, envfmt, 2, &v, 0, 255);
+               rep->re_pcidev = v;
+               v = 0;
+               (void) env_parse(envvar, envfmt, 3, &v, 0, 255);
+               rep->re_pcifunc = v;
+       }
+
+       pci_init();
+
+       for (h = 1; h >= 0; h--) {
+               for (i = 0, rep = re_table; i < RE_PORT_NR; i++, rep++) {
+                       if (((rep->re_pcibus | rep->re_pcidev |
+                               rep->re_pcifunc) != 0) != h) {
+                               continue;
+                       }
+                       if (rl_probe(rep))
+                               rep->re_seen = TRUE;
+               }
+       }
+}
+
+/*===========================================================================*
+ *                             rl_probe                                     *
+ *===========================================================================*/
+static int rl_probe(rep)
+re_t *rep;
+{
+       int i, r, devind, just_one;
+       u16_t vid, did;
+       u32_t bar;
+       u8_t ilr;
+       char *dname;
+
+       if ((rep->re_pcibus | rep->re_pcidev | rep->re_pcifunc) != 0) {
+               /* Look for specific PCI device */
+               r = pci_find_dev(rep->re_pcibus, rep->re_pcidev,
+                       rep->re_pcifunc, &devind);
+               if (r == 0) {
+                       printf("%s: no PCI found at %d.%d.%d\n",
+                               rep->re_name, rep->re_pcibus,
+                               rep->re_pcidev, rep->re_pcifunc);
+                       return 0;
+               }
+               pci_ids(devind, &vid, &did);
+               just_one = TRUE;
+       } else {
+               r = pci_first_dev(&devind, &vid, &did);
+               if (r == 0)
+                       return 0;
+               just_one = FALSE;
+       }
+
+       for (;;) {
+               for (i = 0; pcitab[i].vid != 0; i++) {
+                       if (pcitab[i].vid != vid)
+                               continue;
+                       if (pcitab[i].did != did)
+                               continue;
+                       if (pcitab[i].checkclass) {
+                               panic("rtl_probe",
+                                       "class check not implemented", NO_NUM);
+                       }
+                       break;
+               }
+               if (pcitab[i].vid != 0)
+                       break;
+
+               if (just_one) {
+                       printf("%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
+                               rep->re_name, vid, did,
+                               rep->re_pcibus,
+                               rep->re_pcidev, rep->re_pcifunc);
+                       return 0;
+               }
+
+               r = pci_next_dev(&devind, &vid, &did);
+               if (!r)
+                       return 0;
+       }
+
+       dname = pci_dev_name(vid, did);
+       if (!dname)
+               dname = "unknown device";
+       printf("%s: ", rep->re_name);
+       printf("%s (%x/%x) at %s\n", dname, vid, did, pci_slot_name(devind));
+
+       pci_reserve(devind);
+       bar = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
+       if (bar < 0x400) {
+               panic("rtl_probe",
+                       "base address is not properly configured", NO_NUM);
+       }
+       rep->re_base_port = bar;
+
+       ilr = pci_attr_r8(devind, PCI_ILR);
+       rep->re_irq = ilr;
+       if (debug) {
+               printf("%s: using I/O address 0x%lx, IRQ %d\n",
+                       rep->re_name, (unsigned long)bar, ilr);
+       }
+
+       return TRUE;
+}
+
+/*===========================================================================*
+ *                             rl_conf_hw                                   *
+ *===========================================================================*/
+static void rl_conf_hw(rep)
+re_t *rep;
+{
+       static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0        /* ,... */ };
+
+       rep->re_mode = REM_DISABLED;            /* Superfluous */
+
+       if (rep->re_seen)
+               rep->re_mode = REM_ENABLED;     /* PCI device is present */
+       if (rep->re_mode != REM_ENABLED)
+               return;
+
+       rep->re_flags = REF_EMPTY;
+       rep->re_link_up = 0;
+       rep->re_got_int = 0;
+       rep->re_send_int = 0;
+       rep->re_report_link = 0;
+       rep->re_need_reset = 0;
+       rep->re_tx_alive = 0;
+       rep->re_rx_head = 0;
+       rep->re_read_s = 0;
+       rep->re_tx_head = 0;
+       rep->re_stat = empty_stat;
+       rep->dtcc_counter = 0;
+}
+
+/*===========================================================================*
+ *                             rl_init_buf                                  *
+ *===========================================================================*/
+static void rl_init_buf(rep)
+re_t *rep;
+{
+       size_t rx_bufsize, tx_bufsize, rx_descsize, tx_descsize, tot_bufsize;
+       struct re_desc *desc;
+       phys_bytes buf;
+       char *mallocbuf;
+       int d;
+
+       assert(!rep->setup);
+
+       /* Allocate receive and transmit descriptors */
+       rx_descsize = (N_RX_DESC * sizeof(struct re_desc));
+       tx_descsize = (N_TX_DESC * sizeof(struct re_desc));
+
+       /* Allocate receive and transmit buffers */
+       tx_bufsize = ETH_MAX_PACK_SIZE_TAGGED;
+       if (tx_bufsize % 4)
+               tx_bufsize += 4-(tx_bufsize % 4);       /* Align */
+       rx_bufsize = RX_BUFSIZE;
+       tot_bufsize = rx_descsize + tx_descsize;
+       tot_bufsize += (N_TX_DESC * tx_bufsize) + (N_RX_DESC * rx_bufsize);
+       tot_bufsize += sizeof(struct re_dtcc);
+
+       if (tot_bufsize % 4096)
+               tot_bufsize += 4096 - (tot_bufsize % 4096);
+
+       if (!(mallocbuf = alloc_contig(tot_bufsize, AC_ALIGN64K, &buf)))
+               panic("RTL8169", "Couldn't allocate kernel buffer", NO_NUM);
+
+       /* Rx Descriptor */
+       rep->re_rx_desc = (re_desc *)mallocbuf;
+       rep->p_rx_desc = buf;
+       memset(mallocbuf, 0x00, rx_descsize);
+       buf += rx_descsize;
+       mallocbuf += rx_descsize;
+
+       /* Tx Descriptor */
+       rep->re_tx_desc = (re_desc *)mallocbuf;
+       rep->p_tx_desc = buf;
+       memset(mallocbuf, 0x00, tx_descsize);
+       buf += tx_descsize;
+       mallocbuf += tx_descsize;
+
+       desc = rep->re_rx_desc;
+       for (d = 0; d < N_RX_DESC; d++) {
+               /* Setting Rx buffer */
+               rep->re_rx[d].ret_buf = buf;
+               rep->re_rx[d].v_ret_buf = mallocbuf;
+               buf += rx_bufsize;
+               mallocbuf += rx_bufsize;
+
+               /* Setting Rx descriptor */
+               if (d == (N_RX_DESC - 1)) /* Last descriptor? if so, set the EOR bit */
+                       desc->status =  DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
+               else
+                       desc->status =  DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
+
+               desc->addr_low =  rep->re_rx[d].ret_buf;
+               desc++;
+       }
+       desc = rep->re_tx_desc;
+       for (d = 0; d < N_TX_DESC; d++) {
+               rep->re_tx[d].ret_busy = FALSE;
+               rep->re_tx[d].ret_buf = buf;
+               rep->re_tx[d].v_ret_buf = mallocbuf;
+               buf += tx_bufsize;
+               mallocbuf += tx_bufsize;
+
+               /* Setting Tx descriptor */
+               desc->addr_low =  rep->re_tx[d].ret_buf;
+               desc++;
+       }
+
+       /* Dump Tally Counter buffer */
+       rep->dtcc_buf = buf;
+       rep->v_dtcc_buf = (re_dtcc *)mallocbuf;
+
+       rep->setup = 1;
+}
+
+/*===========================================================================*
+ *                             rl_init_hw                                   *
+ *===========================================================================*/
+static void rl_init_hw(rep)
+re_t *rep;
+{
+       int s, i;
+
+       rep->re_flags = REF_EMPTY;
+       rep->re_flags |= REF_ENABLED;
+
+       /*
+        * Set the interrupt handler. The policy is to only send HARD_INT
+        * notifications. Don't reenable interrupts automatically. The id
+        * that is passed back is the interrupt line number.
+        */
+       rep->re_hook_id = rep->re_irq;
+       if ((s = sys_irqsetpolicy(rep->re_irq, 0, &rep->re_hook_id)) != OK)
+               printf("RTL8169: error, couldn't set IRQ policy: %d\n", s);
+
+       rl_reset_hw(rep);
+
+       if ((s = sys_irqenable(&rep->re_hook_id)) != OK)
+               printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
+
+       printf("%s: model: %s mac: 0x%08lx\n",
+               rep->re_name, rep->re_model, rep->re_mac);
+
+       rl_confaddr(rep);
+       if (debug) {
+               printf("%s: Ethernet address ", rep->re_name);
+               for (i = 0; i < 6; i++) {
+                       printf("%x%c", rep->re_address.ea_addr[i],
+                               i < 5 ? ':' : '\n');
+               }
+       }
+}
+
+static void rtl8169s_phy_config(port_t port)
+{
+       mdio_write(port, 0x1f, 0x0001);
+       mdio_write(port, 0x06, 0x006e);
+       mdio_write(port, 0x08, 0x0708);
+       mdio_write(port, 0x15, 0x4000);
+       mdio_write(port, 0x18, 0x65c7);
+
+       mdio_write(port, 0x1f, 0x0001);
+       mdio_write(port, 0x03, 0x00a1);
+       mdio_write(port, 0x02, 0x0008);
+       mdio_write(port, 0x01, 0x0120);
+       mdio_write(port, 0x00, 0x1000);
+       mdio_write(port, 0x04, 0x0800);
+       mdio_write(port, 0x04, 0x0000);
+
+       mdio_write(port, 0x03, 0xff41);
+       mdio_write(port, 0x02, 0xdf60);
+       mdio_write(port, 0x01, 0x0140);
+       mdio_write(port, 0x00, 0x0077);
+       mdio_write(port, 0x04, 0x7800);
+       mdio_write(port, 0x04, 0x7000);
+
+       mdio_write(port, 0x03, 0x802f);
+       mdio_write(port, 0x02, 0x4f02);
+       mdio_write(port, 0x01, 0x0409);
+       mdio_write(port, 0x00, 0xf0f9);
+       mdio_write(port, 0x04, 0x9800);
+       mdio_write(port, 0x04, 0x9000);
+
+       mdio_write(port, 0x03, 0xdf01);
+       mdio_write(port, 0x02, 0xdf20);
+       mdio_write(port, 0x01, 0xff95);
+       mdio_write(port, 0x00, 0xba00);
+       mdio_write(port, 0x04, 0xa800);
+       mdio_write(port, 0x04, 0xa000);
+
+       mdio_write(port, 0x03, 0xff41);
+       mdio_write(port, 0x02, 0xdf20);
+       mdio_write(port, 0x01, 0x0140);
+       mdio_write(port, 0x00, 0x00bb);
+       mdio_write(port, 0x04, 0xb800);
+       mdio_write(port, 0x04, 0xb000);
+
+       mdio_write(port, 0x03, 0xdf41);
+       mdio_write(port, 0x02, 0xdc60);
+       mdio_write(port, 0x01, 0x6340);
+       mdio_write(port, 0x00, 0x007d);
+       mdio_write(port, 0x04, 0xd800);
+       mdio_write(port, 0x04, 0xd000);
+
+       mdio_write(port, 0x03, 0xdf01);
+       mdio_write(port, 0x02, 0xdf20);
+       mdio_write(port, 0x01, 0x100a);
+       mdio_write(port, 0x00, 0xa0ff);
+       mdio_write(port, 0x04, 0xf800);
+       mdio_write(port, 0x04, 0xf000);
+
+       mdio_write(port, 0x1f, 0x0000);
+       mdio_write(port, 0x0b, 0x0000);
+       mdio_write(port, 0x00, 0x9200);
+}
+
+static void rtl8169scd_phy_config(port_t port)
+{
+       mdio_write(port, 0x1f, 0x0001);
+       mdio_write(port, 0x04, 0x0000);
+       mdio_write(port, 0x03, 0x00a1);
+       mdio_write(port, 0x02, 0x0008);
+       mdio_write(port, 0x01, 0x0120);
+       mdio_write(port, 0x00, 0x1000);
+       mdio_write(port, 0x04, 0x0800);
+       mdio_write(port, 0x04, 0x9000);
+       mdio_write(port, 0x03, 0x802f);
+       mdio_write(port, 0x02, 0x4f02);
+       mdio_write(port, 0x01, 0x0409);
+       mdio_write(port, 0x00, 0xf099);
+       mdio_write(port, 0x04, 0x9800);
+       mdio_write(port, 0x04, 0xa000);
+       mdio_write(port, 0x03, 0xdf01);
+       mdio_write(port, 0x02, 0xdf20);
+       mdio_write(port, 0x01, 0xff95);
+       mdio_write(port, 0x00, 0xba00);
+       mdio_write(port, 0x04, 0xa800);
+       mdio_write(port, 0x04, 0xf000);
+       mdio_write(port, 0x03, 0xdf01);
+       mdio_write(port, 0x02, 0xdf20);
+       mdio_write(port, 0x01, 0x101a);
+       mdio_write(port, 0x00, 0xa0ff);
+       mdio_write(port, 0x04, 0xf800);
+       mdio_write(port, 0x04, 0x0000);
+       mdio_write(port, 0x1f, 0x0000);
+
+       mdio_write(port, 0x1f, 0x0001);
+       mdio_write(port, 0x10, 0xf41b);
+       mdio_write(port, 0x14, 0xfb54);
+       mdio_write(port, 0x18, 0xf5c7);
+       mdio_write(port, 0x1f, 0x0000);
+
+       mdio_write(port, 0x1f, 0x0001);
+       mdio_write(port, 0x17, 0x0cc0);
+       mdio_write(port, 0x1f, 0x0000);
+}
+
+/*===========================================================================*
+ *                             rl_reset_hw                                  *
+ *===========================================================================*/
+static void rl_reset_hw(rep)
+re_t *rep;
+{
+       port_t port;
+       u32_t t;
+       int i;
+       clock_t t0, t1;
+
+       port = rep->re_base_port;
+
+       rl_outw(port, RL_IMR, 0x0000);
+
+       /* Reset the device */
+       printf("rl_reset_hw: (before reset) port = 0x%x, RL_CR = 0x%x\n",
+               port, rl_inb(port, RL_CR));
+       rl_outb(port, RL_CR, RL_CR_RST);
+       getuptime(&t0);
+       do {
+               if (!(rl_inb(port, RL_CR) & RL_CR_RST))
+                       break;
+       } while (getuptime(&t1) == OK && (t1 - t0) < system_hz);
+       printf("rl_reset_hw: (after reset) port = 0x%x, RL_CR = 0x%x\n",
+               port, rl_inb(port, RL_CR));
+       if (rl_inb(port, RL_CR) & RL_CR_RST)
+               printf("rtl8169: reset failed to complete");
+       rl_outw(port, RL_ISR, 0xFFFF);
+
+       /* Get Model and MAC info */
+       t = rl_inl(port, RL_TCR);
+       rep->re_mac = (t & (RL_TCR_HWVER_AM | RL_TCR_HWVER_BM));
+       switch (rep->re_mac) {
+       case RL_TCR_HWVER_RTL8169:
+               rep->re_model = "RTL8169";
+
+               printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+               rl_outw(port, 0x82, 0x01);
+               break;
+       case RL_TCR_HWVER_RTL8169S:
+               rep->re_model = "RTL8169S";
+
+               rtl8169s_phy_config(port);
+
+               printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+               rl_outw(port, 0x82, 0x01);
+               printf("Set PHY Reg 0x0bh = 0x00h\n");
+               mdio_write(port, 0x0b, 0x0000);         /* w 0x0b 15 0 0 */
+               break;
+       case RL_TCR_HWVER_RTL8110S:
+               rep->re_model = "RTL8110S";
+
+               rtl8169s_phy_config(port);
+
+               printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+               rl_outw(port, 0x82, 0x01);
+               break;
+       case RL_TCR_HWVER_RTL8169SB:
+               rep->re_model = "RTL8169SB";
+
+               mdio_write(port, 0x1f, 0x02);
+               mdio_write(port, 0x01, 0x90d0);
+               mdio_write(port, 0x1f, 0x00);
+
+               printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+               rl_outw(port, 0x82, 0x01);
+               break;
+       case RL_TCR_HWVER_RTL8110SCd:
+               rep->re_model = "RTL8110SCd";
+
+               rtl8169scd_phy_config(port);
+
+               printf("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
+               rl_outw(port, 0x82, 0x01);
+               break;
+       default:
+               rep->re_model = "Unknown";
+               rep->re_mac = t;
+               break;
+       }
+
+       mdio_write(port, MII_CTRL, MII_CTRL_RST);
+       for (i = 0; i < 1000; i++) {
+               t = mdio_read(port, MII_CTRL);
+               if (!(t & MII_CTRL_RST))
+                       break;
+               else
+                       micro_delay(100);
+       }
+
+       t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_DM | MII_CTRL_SP_1000;
+       mdio_write(port, MII_CTRL, t);
+
+       t = mdio_read(port, MII_ANA);
+       t |= MII_ANA_10THD | MII_ANA_10TFD | MII_ANA_100TXHD | MII_ANA_100TXFD;
+       t |= MII_ANA_PAUSE_SYM | MII_ANA_PAUSE_ASYM;
+       mdio_write(port, MII_ANA, t);
+
+       t = mdio_read(port, MII_1000_CTRL) | 0x300;
+       mdio_write(port, MII_1000_CTRL, t);
+
+       /* Restart Auto-Negotiation Process */
+       t = mdio_read(port, MII_CTRL) | MII_CTRL_ANE | MII_CTRL_RAN;
+       mdio_write(port, MII_CTRL, t);
+
+       rl_outw(port, RL_9346CR, RL_9346CR_EEM_CONFIG); /* Unlock */
+
+       t = rl_inw(port, RL_CPLUSCMD);
+       if ((rep->re_mac == RL_TCR_HWVER_RTL8169S) ||
+           (rep->re_mac == RL_TCR_HWVER_RTL8110S)) {
+               printf("Set MAC Reg C+CR Offset 0xE0. "
+                       "Bit-3 and bit-14 MUST be 1\n");
+               rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW | (1 << 14));
+       } else
+               rl_outw(port, RL_CPLUSCMD, t | RL_CPLUS_MULRW);
+
+       rl_outw(port, RL_INTRMITIGATE, 0x00);
+
+       t = rl_inb(port, RL_CR);
+       rl_outb(port, RL_CR, t | RL_CR_RE | RL_CR_TE);
+
+       /* Initialize Rx */
+       rl_outw(port, RL_RMS, RX_BUFSIZE);      /* Maximum rx packet size */
+       t = rl_inl(port, RL_RCR) & RX_CONFIG_MASK;
+       rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | t);
+       rl_outl(port, RL_RDSAR_LO, rep->p_rx_desc);
+       rl_outl(port, RL_RDSAR_HI, 0x00);       /* For 64 bit */
+
+       /* Initialize Tx */
+       rl_outw(port, RL_ETTHR, 0x3f);          /* No early transmit */
+       rl_outl(port, RL_TCR, RL_TCR_MXDMA_2048 | RL_TCR_IFG_STD);
+       rl_outl(port, RL_TNPDS_LO, rep->p_tx_desc);
+       rl_outl(port, RL_TNPDS_HI, 0x00);       /* For 64 bit */
+
+       rl_outw(port, RL_9346CR, RL_9346CR_EEM_NORMAL); /* Lock */
+
+       rl_outw(port, RL_MPC, 0x00);
+       rl_outw(port, RL_MULINT, rl_inw(port, RL_MULINT) & 0xF000);
+       rl_outw(port, RL_IMR, RE_INTR_MASK);
+}
+
+/*===========================================================================*
+ *                             rl_confaddr                                  *
+ *===========================================================================*/
+static void rl_confaddr(rep)
+re_t *rep;
+{
+       static char eakey[] = RL_ENVVAR "#_EA";
+       static char eafmt[] = "x:x:x:x:x:x";
+
+       int i;
+       port_t port;
+       u32_t w;
+       long v;
+
+       /* User defined ethernet address? */
+       eakey[sizeof(RL_ENVVAR)-1] = '0' + (rep-re_table);
+
+       port = rep->re_base_port;
+
+       for (i = 0; i < 6; i++) {
+               if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
+                       break;
+               rep->re_address.ea_addr[i] = v;
+       }
+
+       if (i != 0 && i != 6)
+               env_panic(eakey);       /* It's all or nothing */
+
+       /* Should update ethernet address in hardware */
+       if (i == 6) {
+               port = rep->re_base_port;
+               rl_outb(port, RL_9346CR, RL_9346CR_EEM_CONFIG);
+               w = 0;
+               for (i = 0; i < 4; i++)
+                       w |= (rep->re_address.ea_addr[i] << (i * 8));
+               rl_outl(port, RL_IDR, w);
+               w = 0;
+               for (i = 4; i < 6; i++)
+                       w |= (rep->re_address.ea_addr[i] << ((i-4) * 8));
+               rl_outl(port, RL_IDR + 4, w);
+               rl_outb(port, RL_9346CR, RL_9346CR_EEM_NORMAL);
+       }
+
+       /* Get ethernet address */
+       for (i = 0; i < 6; i++)
+               rep->re_address.ea_addr[i] = rl_inb(port, RL_IDR+i);
+}
+
+/*===========================================================================*
+ *                             rl_rec_mode                                  *
+ *===========================================================================*/
+static void rl_rec_mode(rep)
+re_t *rep;
+{
+       port_t port;
+       u32_t rcr;
+       u32_t mc_filter[2];             /* Multicast hash filter */
+
+       port = rep->re_base_port;
+
+       mc_filter[1] = mc_filter[0] = 0xffffffff;
+       rl_outl(port, RL_MAR + 0, mc_filter[0]);
+       rl_outl(port, RL_MAR + 4, mc_filter[1]);
+
+       rcr = rl_inl(port, RL_RCR);
+       rcr &= ~(RL_RCR_AB | RL_RCR_AM | RL_RCR_APM | RL_RCR_AAP);
+       if (rep->re_flags & REF_PROMISC)
+               rcr |= RL_RCR_AB | RL_RCR_AM | RL_RCR_AAP;
+       if (rep->re_flags & REF_BROAD)
+               rcr |= RL_RCR_AB;
+       if (rep->re_flags & REF_MULTI)
+               rcr |= RL_RCR_AM;
+       rcr |= RL_RCR_APM;
+       rl_outl(port, RL_RCR, RL_RCR_RXFTH_UNLIM | RL_RCR_MXDMA_1024 | rcr);
+}
+
+void transmittest(re_t *rep)
+{
+       int tx_head;
+       re_desc *desc;
+
+       tx_head = rep->re_tx_head;
+       desc = rep->re_tx_desc;
+       desc += tx_head;
+
+       if(rep->re_tx[tx_head].ret_busy) {
+               do {
+                       message m;
+                       int r;
+                       if ((r = receive(ANY, &m)) != OK)
+                               panic("rtl8169", "receive failed", r);
+               } while(m.m_source != HARDWARE);
+               assert(!(rep->re_flags & REF_SEND_AVAIL));
+               rep->re_flags |= REF_SEND_AVAIL;
+       }
+
+       return;
+}
+
+/*===========================================================================*
+ *                             rl_readv_s                                   *
+ *===========================================================================*/
+static void rl_readv_s(mp, from_int)
+message *mp;
+int from_int;
+{
+       int i, j, n, s, dl_port, re_client, count, size, index;
+       port_t port;
+       unsigned totlen, packlen;
+       phys_bytes src_phys, iov_src;
+       re_desc *desc;
+       u32_t rxstat = 0x12345678;
+       re_t *rep;
+       iovec_s_t *iovp;
+       int cps;
+       int iov_offset = 0;
+
+       dl_port = mp->DL_PORT;
+       count = mp->DL_COUNT;
+       if (dl_port < 0 || dl_port >= RE_PORT_NR)
+               panic("rtl8169", " illegal port", dl_port);
+       rep = &re_table[dl_port];
+       re_client = mp->DL_PROC;
+       rep->re_client = re_client;
+
+       assert(rep->re_mode == REM_ENABLED);
+       assert(rep->re_flags & REF_ENABLED);
+
+       port = rep->re_base_port;
+
+       /*
+        * Assume that the RL_CR_BUFE check was been done by rl_checks_ints
+        */
+       if (!from_int && (rl_inb(port, RL_CR) & RL_CR_BUFE))
+               goto suspend;           /* Receive buffer is empty, suspend */
+
+       index = rep->re_rx_head;
+readvs_test_loop:
+       desc = rep->re_rx_desc;
+       desc += index;
+readvs_loop:
+       rxstat = desc->status;
+
+       if (rxstat & DESC_OWN)
+               goto suspend;
+
+       if (rxstat & DESC_RX_CRC)
+               rep->re_stat.ets_CRCerr++;
+
+       if ((rxstat & (DESC_FS | DESC_LS)) != (DESC_FS | DESC_LS)) {
+               printf("rl_readv_s: packet is fragmented\n");
+               /* Fix the fragmented packet */
+               if (index == N_RX_DESC - 1) {
+                       desc->status =  DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
+                       index = 0;
+                       desc = rep->re_rx_desc;
+               } else {
+                       desc->status =  DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
+                       index++;
+                       desc++;
+               }
+               goto readvs_loop;       /* Loop until we get correct packet */
+       }
+
+       totlen = rxstat & DESC_RX_LENMASK;
+       if (totlen < 8 || totlen > 2 * ETH_MAX_PACK_SIZE) {
+               /* Someting went wrong */
+               printf("rl_readv_s: bad length (%u) in status 0x%08lx\n",
+                       totlen, rxstat);
+               panic(NULL, NULL, NO_NUM);
+       }
+
+       /* Should subtract the CRC */
+       packlen = totlen - ETH_CRC_SIZE;
+
+       size = 0;
+       src_phys = rep->re_rx[index].ret_buf;
+       for (i = 0; i < count; i += IOVEC_NR,
+               iov_src += IOVEC_NR * sizeof(rep->re_iovec_s[0]),
+               iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
+       {
+               n = IOVEC_NR;
+               if (i + n > count)
+                       n = count-i;
+               cps = sys_safecopyfrom(re_client, mp->DL_GRANT, iov_offset,
+                       (vir_bytes) rep->re_iovec_s,
+                       n * sizeof(rep->re_iovec_s[0]), D);
+               if (cps != OK) {
+                       panic(__FILE__, "rl_readv_s: sys_safecopyfrom failed",
+                               cps);
+               }
+
+               for (j = 0, iovp = rep->re_iovec_s; j < n; j++, iovp++) {
+                       s = iovp->iov_size;
+                       if (size + s > packlen) {
+                               assert(packlen > size);
+                               s = packlen-size;
+                       }
+
+                       cps = sys_safecopyto(re_client, iovp->iov_grant, 0,
+                               (vir_bytes) rep->re_rx[index].v_ret_buf + size, s, D);
+                       if (cps != OK)
+                               panic(__FILE__,
+                               "rl_readv_s: sys_safecopyto failed", cps);
+
+                       size += s;
+                       if (size == packlen)
+                               break;
+               }
+               if (size == packlen)
+                       break;
+       }
+       if (size < packlen)
+               assert(0);
+
+       rep->re_stat.ets_packetR++;
+       rep->re_read_s = packlen;
+       if (index == N_RX_DESC - 1) {
+               desc->status =  DESC_EOR | DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
+               index = 0;
+       } else {
+               desc->status =  DESC_OWN | (RX_BUFSIZE & DESC_RX_LENMASK);
+               index++;
+       }
+       rep->re_rx_head = index;
+       assert(rep->re_rx_head < N_RX_DESC);
+       rep->re_flags = (rep->re_flags & ~REF_READING) | REF_PACK_RECV;
+
+       if (!from_int)
+               reply(rep, OK, FALSE);
+
+       return;
+
+suspend:
+       if (from_int) {
+               assert(rep->re_flags & REF_READING);
+
+               /* No need to store any state */
+               return;
+       }
+
+       rep->re_rx_mess = *mp;
+       assert(!(rep->re_flags & REF_READING));
+       rep->re_flags |= REF_READING;
+
+       reply(rep, OK, FALSE);
+}
+
+/*===========================================================================*
+ *                             rl_writev_s                                  *
+ *===========================================================================*/
+static void rl_writev_s(mp, from_int)
+message *mp;
+int from_int;
+{
+       phys_bytes iov_src;
+       int i, j, n, s, port, count, size;
+       int tx_head, re_client;
+       re_t *rep;
+       iovec_s_t *iovp;
+       re_desc *desc;
+       char *ret;
+       int cps;
+       int iov_offset = 0;
+
+       port = mp->DL_PORT;
+       count = mp->DL_COUNT;
+       if (port < 0 || port >= RE_PORT_NR)
+               panic("rtl8169", "illegal port", port);
+       rep = &re_table[port];
+       assert(mp);
+       assert(port >= 0 && port < RE_PORT_NR);
+       assert(rep->setup);
+       re_client = mp->DL_PROC;
+       rep->re_client = re_client;
+
+       assert(rep->re_mode == REM_ENABLED);
+       assert(rep->re_flags & REF_ENABLED);
+
+       if (from_int) {
+               assert(rep->re_flags & REF_SEND_AVAIL);
+               rep->re_flags &= ~REF_SEND_AVAIL;
+               rep->re_send_int = FALSE;
+               rep->re_tx_alive = TRUE;
+       }
+
+       tx_head = rep->re_tx_head;
+
+       desc = rep->re_tx_desc;
+       desc += tx_head;
+
+       if(!desc || !rep->re_tx_desc) {
+               printf("desc 0x%lx, re_tx_desc 0x%lx, tx_head %d, setup %d\n",
+                       desc, rep->re_tx_desc, tx_head, rep->setup);
+       }
+
+       assert(rep->re_tx_desc);
+       assert(rep->re_tx_head >= 0 && rep->re_tx_head < N_TX_DESC);
+
+       assert(desc);
+
+
+       if (rep->re_tx[tx_head].ret_busy) {
+               assert(!(rep->re_flags & REF_SEND_AVAIL));
+               rep->re_flags |= REF_SEND_AVAIL;
+               if (rep->re_tx[tx_head].ret_busy)
+                       goto suspend;
+
+               /*
+                * Race condition, the interrupt handler may clear re_busy
+                * before we got a chance to set REF_SEND_AVAIL. Checking
+                * ret_busy twice should be sufficient.
+                */
+#if VERBOSE
+               printf("rl_writev_s: race detected\n");
+#endif
+               rep->re_flags &= ~REF_SEND_AVAIL;
+               rep->re_send_int = FALSE;
+       }
+
+       assert(!(rep->re_flags & REF_SEND_AVAIL));
+       assert(!(rep->re_flags & REF_PACK_SENT));
+
+       size = 0;
+       ret = rep->re_tx[tx_head].v_ret_buf;
+       for (i = 0; i < count; i += IOVEC_NR,
+               iov_src += IOVEC_NR * sizeof(rep->re_iovec_s[0]),
+               iov_offset += IOVEC_NR * sizeof(rep->re_iovec_s[0]))
+       {
+               n = IOVEC_NR;
+               if (i + n > count)
+                       n = count - i;
+               cps = sys_safecopyfrom(re_client, mp->DL_GRANT, iov_offset,
+                       (vir_bytes) rep->re_iovec_s,
+                       n * sizeof(rep->re_iovec_s[0]), D);
+               if (cps != OK) {
+                       panic(__FILE__, "rl_writev_s: sys_safecopyfrom failed",
+                               cps);
+               }
+
+               for (j = 0, iovp = rep->re_iovec_s; j < n; j++, iovp++) {
+                       s = iovp->iov_size;
+                       if (size + s > ETH_MAX_PACK_SIZE_TAGGED)
+                               panic("rtl8169", "invalid packet size", NO_NUM);
+
+                       cps = sys_safecopyfrom(re_client, iovp->iov_grant, 0,
+                               (vir_bytes) ret, s, D);
+                       if (cps != OK) {
+                               panic(__FILE__,
+                                       "rl_writev_s: sys_safecopyfrom failed",
+                                       cps);
+                       }
+                       size += s;
+                       ret += s;
+               }
+       }
+       assert(desc);
+       if (size < ETH_MIN_PACK_SIZE)
+               panic("rtl8169", "invalid packet size", size);
+
+       rep->re_tx[tx_head].ret_busy = TRUE;
+
+       if (tx_head == N_TX_DESC - 1) {
+               desc->status =  DESC_EOR | DESC_OWN | DESC_FS | DESC_LS | size;
+               tx_head = 0;
+       } else {
+               desc->status =  DESC_OWN | DESC_FS | DESC_LS | size;
+               tx_head++;
+       }
+
+       assert(tx_head < N_TX_DESC);
+       rep->re_tx_head = tx_head;
+
+       rl_outl(rep->re_base_port, RL_TPPOLL, RL_TPPOLL_NPQ);
+       rep->re_flags |= REF_PACK_SENT;
+
+       /*
+        * If the interrupt handler called, don't send a reply. The reply
+        * will be sent after all interrupts are handled.
+        */
+       if (from_int)
+               return;
+       reply(rep, OK, FALSE);
+       return;
+
+suspend:
+       if (from_int)
+               panic("rtl8169", "should not be sending\n", NO_NUM);
+
+       rep->re_tx_mess = *mp;
+       reply(rep, OK, FALSE);
+}
+
+/*===========================================================================*
+ *                             rl_check_ints                                *
+ *===========================================================================*/
+static void rl_check_ints(rep)
+re_t *rep;
+{
+       int re_flags;
+
+       re_flags = rep->re_flags;
+
+       if ((re_flags & REF_READING) &&
+               !(rl_inb(rep->re_base_port, RL_CR) & RL_CR_BUFE))
+       {
+               assert(rep->re_rx_mess.m_type == DL_READV_S);
+               rl_readv_s(&rep->re_rx_mess, TRUE /* from int */);
+       }
+
+       if (rep->re_need_reset)
+               rl_do_reset(rep);
+
+       if (rep->re_send_int) {
+               assert(rep->re_tx_mess.m_type == DL_WRITEV_S);
+               rl_writev_s(&rep->re_tx_mess, TRUE /* from int */);
+       }
+
+       if (rep->re_report_link)
+               rl_report_link(rep);
+
+       if (rep->re_flags & (REF_PACK_SENT | REF_PACK_RECV))
+               reply(rep, OK, TRUE);
+}
+
+/*===========================================================================*
+ *                             rl_report_link                               *
+ *===========================================================================*/
+static void rl_report_link(rep)
+re_t *rep;
+{
+       port_t port;
+       u8_t mii_status;
+
+       rep->re_report_link = FALSE;
+       port = rep->re_base_port;
+
+       mii_status = rl_inb(port, RL_PHYSTAT);
+
+       if (mii_status & RL_STAT_LINK) {
+               rep->re_link_up = 1;
+               printf("%s: link up at ", rep->re_name);
+       } else {
+               rep->re_link_up = 0;
+               printf("%s: link down\n", rep->re_name);
+               return;
+       }
+
+       if (mii_status & RL_STAT_1000)
+               printf("1000 Mbps");
+       else if (mii_status & RL_STAT_100)
+               printf("100 Mbps");
+       else if (mii_status & RL_STAT_10)
+               printf("10 Mbps");
+
+       if (mii_status & RL_STAT_FULLDUP)
+               printf(", full duplex");
+       else
+               printf(", half duplex");
+       printf("\n");
+
+       dump_phy(rep);
+}
+
+/*===========================================================================*
+ *                             rl_do_reset                                  *
+ *===========================================================================*/
+static void rl_do_reset(rep)
+re_t *rep;
+{
+       rep->re_need_reset = FALSE;
+       rl_reset_hw(rep);
+       rl_rec_mode(rep);
+
+       rep->re_tx_head = 0;
+       if (rep->re_flags & REF_SEND_AVAIL) {
+               rep->re_tx[rep->re_tx_head].ret_busy = FALSE;
+               rep->re_send_int = TRUE;
+       }
+}
+
+/*===========================================================================*
+ *                             rl_getstat                                   *
+ *===========================================================================*/
+static void rl_getstat(mp)
+message *mp;
+{
+       int r, port;
+       eth_stat_t stats;
+       re_t *rep;
+
+       port = mp->DL_PORT;
+       if (port < 0 || port >= RE_PORT_NR)
+               panic("rtl8169", "illegal port", port);
+       rep = &re_table[port];
+       rep->re_client = mp->DL_PROC;
+
+       assert(rep->re_mode == REM_ENABLED);
+       assert(rep->re_flags & REF_ENABLED);
+
+       stats = rep->re_stat;
+
+       r = sys_datacopy(SELF, (vir_bytes) &stats, mp->DL_PROC,
+               (vir_bytes) mp->DL_ADDR, sizeof(stats));
+       if (r != OK)
+               panic(__FILE__, "rl_getstat: sys_datacopy failed", r);
+
+       mp->m_type = DL_STAT_REPLY;
+       mp->DL_PORT = port;
+       mp->DL_STAT = OK;
+       r = send(mp->m_source, mp);
+       if (r != OK)
+               panic("RTL8169", "rl_getstat: send failed: %d\n", r);
+}
+
+/*===========================================================================*
+ *                             rl_getstat_s                                 *
+ *===========================================================================*/
+static void rl_getstat_s(mp)
+message *mp;
+{
+       int r, port;
+       eth_stat_t stats;
+       re_t *rep;
+
+       port = mp->DL_PORT;
+       if (port < 0 || port >= RE_PORT_NR)
+               panic("rtl8169", "illegal port", port);
+       rep = &re_table[port];
+       rep->re_client = mp->DL_PROC;
+
+       assert(rep->re_mode == REM_ENABLED);
+       assert(rep->re_flags & REF_ENABLED);
+
+       stats = rep->re_stat;
+
+       r = sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0,
+               (vir_bytes) &stats, sizeof(stats), D);
+       if (r != OK)
+               panic(__FILE__, "rl_getstat_s: sys_safecopyto failed", r);
+
+       mp->m_type = DL_STAT_REPLY;
+       mp->DL_PORT = port;
+       mp->DL_STAT = OK;
+       r = send(mp->m_source, mp);
+       if (r != OK)
+               panic("RTL8169", "rl_getstat_s: send failed: %d\n", r);
+}
+
+
+/*===========================================================================*
+ *                             rl_getname                                   *
+ *===========================================================================*/
+static void rl_getname(mp)
+message *mp;
+{
+       int r;
+
+       strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
+       mp->DL_NAME[sizeof(mp->DL_NAME)-1] = '\0';
+       mp->m_type = DL_NAME_REPLY;
+       r = send(mp->m_source, mp);
+       if (r != OK)
+               panic("RTL8169", "rl_getname: send failed: %d\n", r);
+}
+
+
+/*===========================================================================*
+ *                             reply                                        *
+ *===========================================================================*/
+static void reply(rep, err, may_block)
+re_t *rep;
+int err;
+int may_block;
+{
+       message reply;
+       int status;
+       int r;
+       clock_t now;
+
+       status = 0;
+       if (rep->re_flags & REF_PACK_SENT)
+               status |= DL_PACK_SEND;
+       if (rep->re_flags & REF_PACK_RECV)
+               status |= DL_PACK_RECV;
+
+       reply.m_type = DL_TASK_REPLY;
+       reply.DL_PORT = rep - re_table;
+       reply.DL_PROC = rep->re_client;
+       reply.DL_STAT = status | ((u32_t) err << 16);
+       reply.DL_COUNT = rep->re_read_s;
+       if (OK != (r = getuptime(&now)))
+               panic("rtl8169", "getuptime() failed:", r);
+       reply.DL_CLCK = now;
+
+       r = send(rep->re_client, &reply);
+
+       if (r == ELOCKED && may_block) {
+               printW(); printf("send locked\n");
+               return;
+       }
+
+       if (r < 0) {
+               printf("RTL8169 tried sending to %d, type %d\n",
+                       rep->re_client, reply.m_type);
+               panic("rtl8169", "send failed:", r);
+       }
+
+       rep->re_read_s = 0;
+       rep->re_flags &= ~(REF_PACK_SENT | REF_PACK_RECV);
+}
+
+/*===========================================================================*
+ *                             mess_reply                                   *
+ *===========================================================================*/
+static void mess_reply(req, reply_mess)
+message *req;
+message *reply_mess;
+{
+       if (send(req->m_source, reply_mess) != OK)
+               panic("rtl8169", "unable to mess_reply", NO_NUM);
+}
+
+static void dump_phy(re_t *rep)
+{
+#if VERBOSE
+       port_t port;
+       u32_t t;
+
+       port = rep->re_base_port;
+
+       t = rl_inb(port, RL_CONFIG0);
+       printf("CONFIG0\t\t:");
+       t = t & RL_CFG0_ROM;
+       if (t == RL_CFG0_ROM128K)
+               printf(" 128K Boot ROM");
+       else if (t == RL_CFG0_ROM64K)
+               printf(" 64K Boot ROM");
+       else if (t == RL_CFG0_ROM32K)
+               printf(" 32K Boot ROM");
+       else if (t == RL_CFG0_ROM16K)
+               printf(" 16K Boot ROM");
+       else if (t == RL_CFG0_ROM8K)
+               printf(" 8K Boot ROM");
+       else if (t == RL_CFG0_ROMNO)
+               printf(" No Boot ROM");
+       printf("\n");
+
+       t = rl_inb(port, RL_CONFIG1);
+       printf("CONFIG1\t\t:");
+       if (t & RL_CFG1_LEDS1)
+               printf(" LED1");
+       if (t & RL_CFG1_LEDS0)
+               printf(" LED0");
+       if (t & RL_CFG1_DVRLOAD)
+               printf(" Driver");
+       if (t & RL_CFG1_LWACT)
+               printf(" LWAKE");
+       if (t & RL_CFG1_IOMAP)
+               printf(" IOMAP");
+       if (t & RL_CFG1_MEMMAP)
+               printf(" MEMMAP");
+       if (t & RL_CFG1_VPD)
+               printf(" VPD");
+       if (t & RL_CFG1_PME)
+               printf(" PME");
+       printf("\n");
+
+       t = rl_inb(port, RL_CONFIG2);
+       printf("CONFIG2\t\t:");
+       if (t & RL_CFG2_AUX)
+               printf(" AUX");
+       if (t & RL_CFG2_PCIBW)
+               printf(" PCI-64-Bit");
+       else
+               printf(" PCI-32-Bit");
+       t = t & RL_CFG2_PCICLK;
+       if (t == RL_CFG2_66MHZ)
+               printf(" 66 MHz");
+       else if (t == RL_CFG2_33MHZ)
+               printf(" 33 MHz");
+       printf("\n");
+
+       t = mdio_read(port, MII_CTRL);
+       printf("MII_CTRL\t:");
+       if (t & MII_CTRL_RST)
+               printf(" Reset");
+       if (t & MII_CTRL_LB)
+               printf(" Loopback");
+       if (t & MII_CTRL_ANE)
+               printf(" ANE");
+       if (t & MII_CTRL_PD)
+               printf(" Power-down");
+       if (t & MII_CTRL_ISO)
+               printf(" Isolate");
+       if (t & MII_CTRL_RAN)
+               printf(" RAN");
+       if (t & MII_CTRL_DM)
+               printf(" Full-duplex");
+       if (t & MII_CTRL_CT)
+               printf(" COL-signal");
+       t = t & (MII_CTRL_SP_LSB | MII_CTRL_SP_MSB);
+       if (t == MII_CTRL_SP_10)
+               printf(" 10 Mb/s");
+       else if (t == MII_CTRL_SP_100)
+               printf(" 100 Mb/s");
+       else if (t == MII_CTRL_SP_1000)
+               printf(" 1000 Mb/s");
+       printf("\n");
+
+       t = mdio_read(port, MII_STATUS);
+       printf("MII_STATUS\t:");
+       if (t & MII_STATUS_100T4)
+               printf(" 100Base-T4");
+       if (t & MII_STATUS_100XFD)
+               printf(" 100BaseX-FD");
+       if (t & MII_STATUS_100XHD)
+               printf(" 100BaseX-HD");
+       if (t & MII_STATUS_10FD)
+               printf(" 10Mbps-FD");
+       if (t & MII_STATUS_10HD)
+               printf(" 10Mbps-HD");
+       if (t & MII_STATUS_100T2FD)
+               printf(" 100Base-T2-FD");
+       if (t & MII_STATUS_100T2HD)
+               printf(" 100Base-T2-HD");
+       if (t & MII_STATUS_EXT_STAT)
+               printf(" Ext-stat");
+       if (t & MII_STATUS_RES)
+               printf(" res-0x%lx", t & MII_STATUS_RES);
+       if (t & MII_STATUS_MFPS)
+               printf(" MFPS");
+       if (t & MII_STATUS_ANC)
+               printf(" ANC");
+       if (t & MII_STATUS_RF)
+               printf(" remote-fault");
+       if (t & MII_STATUS_ANA)
+               printf(" ANA");
+       if (t & MII_STATUS_LS)
+               printf(" Link");
+       if (t & MII_STATUS_JD)
+               printf(" Jabber");
+       if (t & MII_STATUS_EC)
+               printf(" Extended-capability");
+       printf("\n");
+
+       t = mdio_read(port, MII_ANA);
+       printf("MII_ANA\t\t: 0x%04lx\n", t);
+
+       t = mdio_read(port, MII_ANLPA);
+       printf("MII_ANLPA\t: 0x%04lx\n", t);
+
+       t = mdio_read(port, MII_ANE);
+       printf("MII_ANE\t\t:");
+       if (t & MII_ANE_RES)
+               printf(" res-0x%lx", t & MII_ANE_RES);
+       if (t & MII_ANE_PDF)
+               printf(" Par-Detect-Fault");
+       if (t & MII_ANE_LPNPA)
+               printf(" LP-Next-Page-Able");
+       if (t & MII_ANE_NPA)
+               printf(" Loc-Next-Page-Able");
+       if (t & MII_ANE_PR)
+               printf(" Page-Received");
+       if (t & MII_ANE_LPANA)
+               printf(" LP-Auto-Neg-Able");
+       printf("\n");
+
+       t = mdio_read(port, MII_1000_CTRL);
+       printf("MII_1000_CTRL\t:");
+       if (t & MII_1000C_FULL)
+               printf(" 1000BaseT-FD");
+       if (t & MII_1000C_HALF)
+               printf(" 1000BaseT-HD");
+       printf("\n");
+
+       t = mdio_read(port, MII_1000_STATUS);
+       if (t) {
+               printf("MII_1000_STATUS\t:");
+               if (t & MII_1000S_LRXOK)
+                       printf(" Local-Receiver");
+               if (t & MII_1000S_RRXOK)
+                       printf(" Remote-Receiver");
+               if (t & MII_1000S_HALF)
+                       printf(" 1000BaseT-HD");
+               if (t & MII_1000S_FULL)
+                       printf(" 1000BaseT-FD");
+               printf("\n");
+
+               t = mdio_read(port, MII_EXT_STATUS);
+               printf("MII_EXT_STATUS\t:");
+               if (t & MII_ESTAT_1000XFD)
+                       printf(" 1000BaseX-FD");
+               if (t & MII_ESTAT_1000XHD)
+                       printf(" 1000BaseX-HD");
+               if (t & MII_ESTAT_1000TFD)
+                       printf(" 1000BaseT-FD");
+               if (t & MII_ESTAT_1000THD)
+                       printf(" 1000BaseT-HD");
+               printf("\n");
+       }
+#endif
+}
+
+static void do_hard_int(void)
+{
+       int i, s;
+
+       for (i = 0; i < RE_PORT_NR; i++) {
+
+               /* Run interrupt handler at driver level. */
+               rl_handler(&re_table[i]);
+
+               /* Reenable interrupts for this hook. */
+               if ((s = sys_irqenable(&re_table[i].re_hook_id)) != OK)
+                       printf("RTL8169: error, couldn't enable interrupts: %d\n", s);
+       }
+}
+
+/*===========================================================================*
+ *                             rl_handler                                   *
+ *===========================================================================*/
+static int rl_handler(rep)
+re_t *rep;
+{
+       int i, port, tx_head, tx_tail, link_up;
+       u16_t isr;
+       re_desc *desc;
+       int_event_check = FALSE;        /* disable check by default */
+
+       port = rep->re_base_port;
+
+       /* Ack interrupt */
+       isr = rl_inw(port, RL_ISR);
+       if(!isr)
+               return;
+       rl_outw(port, RL_ISR, isr);
+       rep->interrupts++;
+
+       if (isr & RL_IMR_FOVW) {
+               isr &= ~RL_IMR_FOVW;
+               /* Should do anything? */
+
+               rep->re_stat.ets_fifoOver++;
+       }
+       if (isr & RL_IMR_PUN) {
+               isr &= ~RL_IMR_PUN;
+
+               /*
+                * Either the link status changed or there was a TX fifo
+                * underrun.
+                */
+               link_up = !(!(rl_inb(port, RL_PHYSTAT) & RL_STAT_LINK));
+               if (link_up != rep->re_link_up) {
+                       rep->re_report_link = TRUE;
+                       rep->re_got_int = TRUE;
+                       int_event_check = TRUE;
+               }
+       }
+
+       if (isr & (RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK)) {
+               if (isr & RL_ISR_RER)
+                       rep->re_stat.ets_recvErr++;
+               isr &= ~(RL_ISR_RDU | RL_ISR_RER | RL_ISR_ROK);
+
+               if (!rep->re_got_int && (rep->re_flags & REF_READING)) {
+                       rep->re_got_int = TRUE;
+                       int_event_check = TRUE;
+               }
+       }
+
+       if ((isr & (RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK)) || 1) {
+               if (isr & RL_ISR_TER)
+                       rep->re_stat.ets_sendErr++;
+               isr &= ~(RL_ISR_TDU | RL_ISR_TER | RL_ISR_TOK);
+
+               /* Transmit completed */
+               tx_head = rep->re_tx_head;
+               tx_tail = tx_head+1;
+               if (tx_tail >= N_TX_DESC)
+                       tx_tail = 0;
+               for (i = 0; i < 2 * N_TX_DESC; i++) {
+                       if (!rep->re_tx[tx_tail].ret_busy) {
+                               /* Strange, this buffer is not in-use.
+                                * Increment tx_tail until tx_head is
+                                * reached (or until we find a buffer that
+                                * is in-use.
+                                */
+                               if (tx_tail == tx_head)
+                                       break;
+                               if (++tx_tail >= N_TX_DESC)
+                                       tx_tail = 0;
+                               assert(tx_tail < N_TX_DESC);
+                               continue;
+                       }
+                       desc = rep->re_tx_desc;
+                       desc += tx_tail;
+                       if (desc->status & DESC_OWN) {
+                               /* Buffer is not yet ready */
+                               break;
+                       }
+
+                       rep->re_stat.ets_packetT++;
+                       rep->re_tx[tx_tail].ret_busy = FALSE;
+
+                       if (++tx_tail >= N_TX_DESC)
+                               tx_tail = 0;
+                       assert(tx_tail < N_TX_DESC);
+
+                       if (rep->re_flags & REF_SEND_AVAIL) {
+                               rep->re_send_int = TRUE;
+                               if (!rep->re_got_int) {
+                                       rep->re_got_int = TRUE;
+                                       int_event_check = TRUE;
+                               }
+                       }
+               }
+               assert(i < 2 * N_TX_DESC);
+       }
+
+       /* Ignore Reserved Interrupt */
+       if (isr & RL_ISR_RES)
+               isr &= ~RL_ISR_RES;
+
+       if (isr)
+               printf("rl_handler: unhandled interrupt isr = 0x%04x\n", isr);
+
+       return 1;
+}
+
+/*===========================================================================*
+ *                             rl_watchdog_f                                *
+ *===========================================================================*/
+static void rl_watchdog_f(tp)
+timer_t *tp;
+{
+       int i;
+       re_t *rep;
+       /* Use a synchronous alarm instead of a watchdog timer. */
+       sys_setalarm(system_hz, 0);
+
+       for (i = 0, rep = &re_table[0]; i < RE_PORT_NR; i++, rep++) {
+               if (rep->re_mode != REM_ENABLED)
+                       continue;
+
+               /* Should collect statistics */
+               if (!(++rep->dtcc_counter % RE_DTCC_VALUE))
+                       rtl8169_update_stat(rep);
+
+               if (!(rep->re_flags & REF_SEND_AVAIL)) {
+                       /* Assume that an idle system is alive */
+                       rep->re_tx_alive = TRUE;
+                       continue;
+               }
+               if (rep->re_tx_alive) {
+                       rep->re_tx_alive = FALSE;
+                       continue;
+               }
+               printf("rl_watchdog_f: resetting port %d mode 0x%x flags 0x%x\n",
+                       i, rep->re_mode, rep->re_flags);
+               printf("tx_head    :%8d  busy %d\t",
+                       rep->re_tx_head, rep->re_tx[rep->re_tx_head].ret_busy);
+               rep->re_need_reset = TRUE;
+               rep->re_got_int = TRUE;
+
+               check_int_events();
+       }
+}
+
diff --git a/drivers/rtl8169/rtl8169.h b/drivers/rtl8169/rtl8169.h
new file mode 100644 (file)
index 0000000..d806c58
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * rtl8169.h
+ */
+
+#define        RL_N_DESC       1024            /* Number of descriptors */
+#define N_RX_DESC      RL_N_DESC       /* Number of receive descriptors */
+#define N_TX_DESC      RL_N_DESC       /* Number of transmit descriptors */
+
+#define RX_BUFSIZE     1536            /* Maximum gigabit ethernet frame size */
+
+/* Transmit Descriptor control */
+#define DESC_RX_LGSEN  0x08000000      /* Large Send */
+#define DESC_RX_IPCS   0x00040000      /* IP Checksum Offload */
+#define DESC_RX_UDPCS  0x00020000      /* UDP Checksum Offload */
+#define DESC_RX_TCPCS  0x00010000      /* TCP Checksum Offload */
+#define DESC_TX_LENMASK        0x0000FFFF      /* Transmit Frame Length Mask */
+
+/* Receive Descriptor control */
+#define DESC_RX_MAR    0x08000000      /* Multicast Address Received */
+#define DESC_RX_PAM    0x04000000      /* Physical Address Matched */
+#define DESC_RX_BAR    0x02000000      /* Broadcast Address Received */
+#define DESC_RX_BOVF   0x01000000      /* Buffer Overflow */
+#define DESC_RX_FOVF   0x00800000      /* FIFO Overflow */
+#define DESC_RX_RWT    0x00400000      /* Receive Watchdog Timer Expired */
+#define DESC_RX_RES    0x00200000      /* Receive Error Summary */
+#define DESC_RX_RUNT   0x00100000      /* Runt Packet */
+#define DESC_RX_CRC    0x00080000      /* CRC Error */
+#define DESC_RX_PID1   0x00040000      /* Protocol ID1 */
+#define DESC_RX_PID0   0x00020000      /* Protocol ID0 */
+#define DESC_RX_IPF    0x00010000      /* IP Checksum Failure */
+#define DESC_RX_UDPF   0x00008000      /* UDP Checksum Failure */
+#define DESC_RX_TCPF   0x00004000      /* TCP Checksum Failure */
+#define DESC_RX_LENMASK        0x00001FFF      /* Receive Frame Length Mask */
+
+/* General Descriptor control */
+#define DESC_OWN       0x80000000      /* Ownership */
+#define DESC_EOR       0x40000000      /* End of Descriptor Ring */
+#define DESC_FS                0x20000000      /* First Segment Descriptor */
+#define DESC_LS                0x10000000      /* Last Segment Descriptor */
+
+
+#define        RL_IDR          0x00    /* Ethernet address
+                                * Note: RL_9346CR_EEM_CONFIG mode is
+                                * required the change the ethernet address.
+                                * Note: 4-byte write access only.
+                                */
+#define        RL_MAR          0x08    /* Multicast */
+#define        RL_DTCCR_LO     0x10    /* Dump Tally Counter Command Register LOW */
+#define        RL_DTCCR_HI     0x14    /* Dump Tally Counter Command Register HIGH */
+#define                RL_DTCCR_CMD    0x08    /* Command */
+#define RL_TNPDS_LO    0x20    /* Transmit Normal Priority Descriptors Start Address LOW */
+#define RL_TNPDS_HI    0x24    /* Transmit Normal Priority Descriptors Start Address HIGH */
+#define RL_THPDS_LO    0x28    /* Transmit High Priority Descriptors Start Address LOW */
+#define RL_THPDS_HI    0x2C    /* Transmit High Priority Descriptors Start Address HIGH */
+#define        RL_FLASH        0x30    /* Flash Memory Read/Write Register */
+#define RL_ERBCR       0x34    /* Early Receive (Rx) Byte Count Register */
+#define RL_ERSR                0x36    /* Early Rx Status Register */
+#define                RL_ERSR_RES     0xF0    /* Reserved */
+#define                RL_ERSR_ERGOOD  0x08    /* Early Rx Good packet */
+#define                RL_ERSR_ERBAD   0x04    /* Early Rx Bad packet */
+#define                RL_ERSR_EROVW   0x02    /* Early Rx OverWrite */
+#define                RL_ERSR_EROK    0x01    /* Early Rx OK */
+#define        RL_CR           0x37    /* Command Register */
+#define                RL_CR_RES0      0xE0    /* Reserved */
+#define                RL_CR_RST       0x10    /* Reset */
+#define                RL_CR_RE        0x08    /* Receiver Enable */
+#define                RL_CR_TE        0x04    /* Transmitter Enable *
+                                        * Note: start with transmit buffer
+                                        * 0 after RL_CR_TE has been reset.
+                                        */
+#define                RL_CR_RES1      0x02    /* Reserved */
+#define                RL_CR_BUFE      0x01    /* Receive Buffer Empty */
+#define        RL_TPPOLL       0x38    /* Transmit Priority Polling Register */
+#define                RL_TPPOLL_HPQ   0x80    /* High Priority Queue Polling */
+#define                RL_TPPOLL_NPQ   0x40    /* Normal Priority Queue Polling */
+#define                RL_TPPOLL_FSW   0x01    /* Forced Software Interrupt */
+#define        RL_IMR          0x3C    /* Interrupt Mask Register */
+#define                RL_IMR_SERR     0x8000  /* System Error */
+#define                RL_IMR_TIMEOUT  0x4000  /* Time Out */
+#define                RL_IMR_RES      0x3E00  /* Reserved */
+#define                RL_IMR_SWINT    0x0100  /* Software Interrupt */
+#define                RL_IMR_TDU      0x0080  /* Tx Descriptor Unavailable */
+#define                RL_IMR_FOVW     0x0040  /* Rx FIFO Overflow */
+#define                RL_IMR_PUN      0x0020  /* Packet Underrun / Link Change */
+#define                RL_IMR_RDU      0x0010  /* Rx Descriptor Unavailable */
+#define                RL_IMR_TER      0x0008  /* Transmit Error */
+#define                RL_IMR_TOK      0x0004  /* Transmit OK */
+#define                RL_IMR_RER      0x0002  /* Receive Error */
+#define                RL_IMR_ROK      0x0001  /* Receive OK */
+#define        RL_ISR          0x3E    /* Interrupt Status Register */
+#define                RL_ISR_SERR     0x8000  /* System Error */
+#define                RL_ISR_TIMEOUT  0x4000  /* Time Out */
+#define                RL_ISR_RES      0x3E00  /* Reserved */
+#define                RL_ISR_SWINT    0x0100  /* Software Interrupt */
+#define                RL_ISR_TDU      0x0080  /* Tx Descriptor Unavailable */
+#define                RL_ISR_FOVW     0x0040  /* Rx FIFO Overflow */
+#define                RL_ISR_PUN      0x0020  /* Packet Underrun / Link Change */
+#define                RL_ISR_RDU      0x0010  /* Rx Descriptor Unavailable */
+#define                RL_ISR_TER      0x0008  /* Transmit Error */
+#define                RL_ISR_TOK      0x0004  /* Transmit OK */
+#define                RL_ISR_RER      0x0002  /* Receive Error */
+#define                RL_ISR_ROK      0x0001  /* Receive OK */
+#define        RL_TCR          0x40    /* Transmit Configuration Register
+                                * Note: RL_CR_TE has to be set to
+                                * set/change RL_TCR.
+                                */
+#define                RL_TCR_RES0     0x80000000 /* Reserved */
+#define                RL_TCR_HWVER_AM 0x7C000000 /* Hardware Version ID A */
+#define                RL_TCR_IFG_M    0x03000000 /* Interframe Gap Time */
+#define                        RL_TCR_IFG_STD          0x03000000 /* IEEE 802.3 std */
+#define                RL_TCR_HWVER_BM 0x00800000 /* Hardware Version ID B */
+#define                        RL_TCR_HWVER_RTL8169    0x00000000 /* RTL8169 */
+#define                        RL_TCR_HWVER_RTL8169S   0x00800000 /* RTL8169S */
+#define                        RL_TCR_HWVER_RTL8110S   0x04000000 /* RTL8110S */
+#define                        RL_TCR_HWVER_RTL8169SB  0x10000000 /* RTL8169sb/8110sb */
+#define                        RL_TCR_HWVER_RTL8110SCd 0x18000000 /* RTL8169sc/8110sc */
+#define                RL_TCR_RES1     0x00380000 /* Reserved */
+#define                RL_TCR_LBK_M    0x00060000 /* Loopback Test */
+#define                        RL_TCR_LBK_NORMAL       0x00000000 /* Normal */
+#define                        RL_TCR_LBK_LOOKBOCK     0x00060000 /* Loopback Mode */
+#define                RL_TCR_CRC      0x00010000 /* (Do not) Append CRC */
+#define                RL_TCR_RES2     0x0000F800 /* Reserved */
+#define                RL_TCR_MXDMA_M  0x00000700 /* Max DMA Burst Size Tx */
+#define                        RL_TCR_MXDMA_16         0x00000000 /* 16 bytes */
+#define                        RL_TCR_MXDMA_32         0x00000100 /* 32 bytes */
+#define                        RL_TCR_MXDMA_64         0x00000200 /* 64 bytes */
+#define                        RL_TCR_MXDMA_128        0x00000300 /* 128 bytes */
+#define                        RL_TCR_MXDMA_128        0x00000300 /* 128 bytes */
+#define                        RL_TCR_MXDMA_256        0x00000400 /* 256 bytes */
+#define                        RL_TCR_MXDMA_512        0x00000500 /* 512 bytes */
+#define                        RL_TCR_MXDMA_1024       0x00000600 /* 1024 bytes */
+#define                        RL_TCR_MXDMA_2048       0x00000700 /* 2048 bytes */
+#define                RL_TCR_TXRR_M   0x000000F0 /* Tx Retry Count */
+#define                RL_TCR_RES3     0x0000000E /* Reserved */
+#define                RL_TCR_CLRABT   0x00000001 /* Clear Abort */
+#define RL_RCR         0x44    /* Receive Configuration Register
+                                * Note: RL_CR_RE has to be set to
+                                * set/change RL_RCR.
+                                */
+#define                RL_RCR_RES0     0xF0000000 /* Reserved */
+#define                RL_RCR_ERTH_M   0x0F000000 /* Early Rx Threshold */
+#define                        RL_RCR_ERTH_0           0x00000000 /* No threshold */
+#define                        RL_RCR_ERTH_1           0x01000000 /* 1/16 */
+#define                        RL_RCR_ERTH_2           0x02000000 /* 2/16 */
+#define                        RL_RCR_ERTH_3           0x03000000 /* 3/16 */
+#define                        RL_RCR_ERTH_4           0x04000000 /* 4/16 */
+#define                        RL_RCR_ERTH_5           0x05000000 /* 5/16 */
+#define                        RL_RCR_ERTH_6           0x06000000 /* 6/16 */
+#define                        RL_RCR_ERTH_7           0x07000000 /* 7/16 */
+#define                        RL_RCR_ERTH_8           0x08000000 /* 8/16 */
+#define                        RL_RCR_ERTH_9           0x09000000 /* 9/16 */
+#define                        RL_RCR_ERTH_10          0x0A000000 /* 10/16 */
+#define                        RL_RCR_ERTH_11          0x0B000000 /* 11/16 */
+#define                        RL_RCR_ERTH_12          0x0C000000 /* 12/16 */
+#define                        RL_RCR_ERTH_13          0x0D000000 /* 13/16 */
+#define                        RL_RCR_ERTH_14          0x0E000000 /* 14/16 */
+#define                        RL_RCR_ERTH_15          0x0F000000 /* 15/16 */
+#define                RL_RCR_RES1     0x00FC0000 /* Reserved */
+#define                RL_RCR_MULERINT 0x00020000 /* Multiple Early Int Select */
+#define                RL_RCR_RER8     0x00010000 /* Receive small error packet */
+#define                RL_RCR_RXFTH_M  0x0000E000 /* Rx FIFO Threshold */
+#define                        RL_RCR_RXFTH_16         0x00000000 /* 16 bytes */
+#define                        RL_RCR_RXFTH_32         0x00002000 /* 32 bytes */
+#define                        RL_RCR_RXFTH_64         0x00004000 /* 64 bytes */
+#define                        RL_RCR_RXFTH_128        0x00006000 /* 128 bytes */
+#define                        RL_RCR_RXFTH_256        0x00008000 /* 256 bytes */
+#define                        RL_RCR_RXFTH_512        0x0000A000 /* 512 bytes */
+#define                        RL_RCR_RXFTH_1024       0x0000C000 /* 1024 bytes */
+#define                        RL_RCR_RXFTH_UNLIM      0x0000E000 /* unlimited */
+#define                RL_RCR_RBLEM_M  0x00001800 /* Rx Buffer Length */
+#define                        RL_RCR_RBLEN_8K         0x00000000 /* 8KB + 16 bytes */
+#define                        RL_RCR_RBLEN_8K_SIZE    (8*1024)
+#define                        RL_RCR_RBLEN_16K        0x00000800 /* 16KB + 16 bytes */
+#define                        RL_RCR_RBLEN_16K_SIZE   (16*1024)
+#define                        RL_RCR_RBLEN_32K        0x00001000 /* 32KB + 16 bytes */
+#define                        RL_RCR_RBLEN_32K_SIZE   (32*1024)
+#define                        RL_RCR_RBLEN_64K        0x00001800 /* 64KB + 16 bytes */
+#define                        RL_RCR_RBLEN_64K_SIZE   (64*1024)
+#define                RL_RCR_MXDMA_M  0x00000700 /* Rx DMA burst size */
+#define                        RL_RCR_MXDMA_16         0x00000000 /* 16 bytes */
+#define                        RL_RCR_MXDMA_32         0x00000100 /* 32 bytes */
+#define                        RL_RCR_MXDMA_64         0x00000200 /* 64 bytes */
+#define                        RL_RCR_MXDMA_128        0x00000300 /* 128 bytes */
+#define                        RL_RCR_MXDMA_256        0x00000400 /* 256 bytes */
+#define                        RL_RCR_MXDMA_512        0x00000500 /* 512 bytes */
+#define                        RL_RCR_MXDMA_1024       0x00000600 /* 1024 bytes */
+#define                        RL_RCR_MXDMA_UNLIM      0x00000700 /* unlimited */
+#define                RL_RCR_WRAP     0x00000080 /* (Do not) Wrap on receive */
+#define                RL_RCR_9356     0x00000040 /* EEPROM 1:9356 0:9346 */
+#define                RL_RCR_AER      0x00000020 /* Accept Error Packets */
+#define                RL_RCR_AR       0x00000010 /* Accept Runt Packets */
+#define                RL_RCR_AB       0x00000008 /* Accept Broadcast Packets */
+#define                RL_RCR_AM       0x00000004 /* Accept Multicast Packets */
+#define                RL_RCR_APM      0x00000002 /* Accept Physical Match Packets */
+#define                RL_RCR_AAP      0x00000001 /* Accept All Packets */
+#define        RL_TCTR         0x48    /* Timer Count Register */
+#define        RL_MPC          0x4C    /* Missed Packet Counter */
+#define        RL_9346CR       0x50    /* 93C46 Command Register */
+#define                RL_9346CR_EEM_M 0xC0    /* Operating Mode */
+#define                        RL_9346CR_EEM_NORMAL    0x00 /* Normal Mode */
+#define                        RL_9346CR_EEM_AUTOLOAD  0x40 /* Load from 93C46 */
+#define                        RL_9346CR_EEM_PROG      0x80 /* 93C46 Programming */
+#define                        RL_9346CR_EEM_CONFIG    0xC0 /* Config Write Enable */
+#define                RL_9346CR_RES   0x30    /* Reserved */
+#define                RL_9346CR_EECS  0x08    /* EECS Pin */
+#define                RL_9346CR_EESK  0x04    /* EESK Pin */
+#define                RL_9346CR_EEDI  0x02    /* EEDI Pin */
+#define                RL_9346CR_EEDO  0x01    /* EEDO Pin */
+#define RL_CONFIG0     0x51    /* Configuration Register 0 */
+#define                RL_CFG0_RES     0x000000F8 /* Reserved */
+#define                RL_CFG0_ROM     0x00000007 /* Select Boot ROM Size */
+#define                        RL_CFG0_ROM128K 0x00000005 /* 128K Boot ROM */
+#define                        RL_CFG0_ROM64K  0x00000004 /* 64K Boot ROM */
+#define                        RL_CFG0_ROM32K  0x00000003 /* 32K Boot ROM */
+#define                        RL_CFG0_ROM16K  0x00000002 /* 16K Boot ROM */
+#define                        RL_CFG0_ROM8K   0x00000001 /* 8K Boot ROM */
+#define                        RL_CFG0_ROMNO   0x00000000 /* No Boot ROM */
+#define RL_CONFIG1     0x52    /* Configuration Register 1 */
+#define                RL_CFG1_LEDS1   0x00000080 /* LED1 */
+#define                RL_CFG1_LEDS0   0x00000040 /* LED0 */
+#define                RL_CFG1_DVRLOAD 0x00000020 /* Driver Load */
+#define                RL_CFG1_LWACT   0x00000010 /* LWAKE Active Mode */
+#define                RL_CFG1_MEMMAP  0x00000008 /* Memory Mapping */
+#define                RL_CFG1_IOMAP   0x00000004 /* I/O Mapping */
+#define                RL_CFG1_VPD     0x00000002 /* Enable Vital Product Data */
+#define                RL_CFG1_PME     0x00000001 /* Power Management Enable */
+#define RL_CONFIG2     0x53    /* Configuration Register 2 */
+#define                RL_CFG2_RES     0x000000E0 /* Reserved */
+#define                RL_CFG2_AUX     0x00000010 /* Auxiliary Power Present Status */
+#define                RL_CFG2_PCIBW   0x00000008 /* PCI Bus Width 1:64 0:32 */
+#define                RL_CFG2_PCICLK  0x00000007 /* PCI Clock Frequency */
+#define                        RL_CFG2_66MHZ   0x00000001 /* 66 MHz */
+#define                        RL_CFG2_33MHZ   0x00000000 /* 33 MHz */
+#define RL_CONFIG3     0x54    /* Configuration Register 3 */
+#define                RL_CFG3_MAGIC   0x00000020 /* Wake up when receives a Magic Packet */
+#define                RL_CFG3_LINKUP  0x00000010 /* Wake up when the cable connection is re-established */
+#define                RL_CFG3_BEACON  0x00000001 /* 8168 only, Reserved in the 8168b */
+#define RL_CONFIG4     0x55    /* Configuration Register 4 */
+#define RL_CONFIG5     0x56    /* Configuration Register 5 */
+#define                RL_CFG5_BWF     0x00000040 /* Accept Broadcast Wakeup Frame */
+#define                RL_CFG5_MWF     0x00000020 /* Accept Multicast Eakeup Frame */
+#define                RL_CFG5_UWF     0x00000010 /* Accept Unicast Wakeup Frame */
+#define                RL_CFG5_LAN     0x00000002 /* LANWake Singnal enable/disable */
+#define                RL_CFG5_PME     0x00000001 /* PME status can be reset by PCI RST# */
+#define RL_TIMERINT    0x58    /* Timer Interrupt Select */
+#define RL_MULINT      0x5C    /* Multiple Interrupt Select */
+/*                     0x5E */ /* Reserved */
+/*                     0x5F */ /* Reserved */
+#define RL_PHYAR       0x60    /* PHY Access */
+#define RL_TBICSR0     0x64    /* TBI Control and Status Register */
+#define RL_TBIANAR     0x68    /* TBI Auto-Negotiation Advertisement Register */
+#define RL_TBILPAR     0x6A    /* TBI Auto-Negotiation Link Partner Ability Register */
+#define RL_PHYSTAT     0x6C    /* MII PHY Status */
+#define                RL_STAT_TBI     0x00000080 /* TBI Enable */
+#define                RL_STAT_TXFLOW  0x00000040 /* Tx Flow Control */
+#define                RL_STAT_RXFLOW  0x00000020 /* Rx Flow Control */
+#define                RL_STAT_1000    0x00000010 /* 1000 Mbps */
+#define                RL_STAT_100     0x00000008 /* 100 Mbps */
+#define                RL_STAT_10      0x00000004 /* 10 Mbps */
+#define                RL_STAT_LINK    0x00000002 /* Link Status */
+#define                RL_STAT_FULLDUP 0x00000001 /* Full Duplex */
+
+#define RL_RMS         0xDA    /* Rx Maximum Size */
+#define RL_CPLUSCMD    0xE0    /* C+ Command Register */
+#define                RL_CPLUS_VLAN   0x00000040 /* Receive VLAN D-tagging Enable */
+#define                RL_CPLUS_CHKSUM 0x00000020 /* Receive Checksum Offload Enable */
+#define                RL_CPLUS_DAC    0x00000010 /* PCI Dual Address Cycles Enable */
+#define                RL_CPLUS_MULRW  0x00000008 /* PCI Multiple Read/Write Enable */
+#define RL_INTRMITIGATE        0xE2    /* Interrupt Mitigate */
+#define RL_RDSAR_LO    0xE4    /* Receive Descriptor Start Address Register
+                                * 256-byte alignment Low*/
+#define RL_RDSAR_HI    0xE8    /* Receive Descriptor Start Address High */
+#define RL_ETTHR       0xEC    /* Early Transmit Threshold Register */
+#define RL_FER         0xF0    /* Function Event Register */
+#define RL_FEMR                0xF4    /* Function Event Mask Register */
+#define RL_FPSR                0xF8    /* Function Present State Register */
+#define RL_FFER                0xFC    /* Function Force Event Register */
+
+/*
+ * Registers in the Machine Independent Interface (MII) to the PHY.
+ * IEEE 802.3 (2000 Edition) Clause 22.
+ */
+
+#define MII_CTRL       0x0     /* Control Register (basic) */
+#define                MII_CTRL_RST    0x8000  /* Reset PHY */
+#define                MII_CTRL_LB     0x4000  /* Enable Loopback Mode */
+#define                MII_CTRL_SP_LSB 0x2000  /* Speed Selection (LSB) */
+#define                MII_CTRL_ANE    0x1000  /* Auto Negotiation Enable */
+#define                MII_CTRL_PD     0x0800  /* Power Down */
+#define                MII_CTRL_ISO    0x0400  /* Isolate */
+#define                MII_CTRL_RAN    0x0200  /* Restart Auto-Negotiation Process */
+#define                MII_CTRL_DM     0x0100  /* Full Duplex */
+#define                MII_CTRL_CT     0x0080  /* Enable COL Signal Test */
+#define                MII_CTRL_SP_MSB 0x0040  /* Speed Selection (MSB) */
+#define                        MII_CTRL_SP_10          0x0000  /* 10 Mb/s */
+#define                        MII_CTRL_SP_100         0x2000  /* 100 Mb/s */
+#define                        MII_CTRL_SP_1000        0x0040  /* 1000 Mb/s */
+#define                        MII_CTRL_SP_RES         0x2040  /* Reserved */
+#define                MII_CTRL_RES    0x003F  /* Reserved */
+#define MII_STATUS     0x1     /* Status Register (basic) */
+#define                MII_STATUS_100T4        0x8000  /* 100Base-T4 support */
+#define                MII_STATUS_100XFD       0x4000  /* 100Base-X FD support */
+#define                MII_STATUS_100XHD       0x2000  /* 100Base-X HD support */
+#define                MII_STATUS_10FD         0x1000  /* 10 Mb/s FD support */
+#define                MII_STATUS_10HD         0x0800  /* 10 Mb/s HD support */
+#define                MII_STATUS_100T2FD      0x0400  /* 100Base-T2 FD support */
+#define                MII_STATUS_100T2HD      0x0200  /* 100Base-T2 HD support */
+#define                MII_STATUS_EXT_STAT     0x0100  /* Supports MII_EXT_STATUS */
+#define                MII_STATUS_RES          0x0080  /* Reserved */
+#define                MII_STATUS_MFPS         0x0040  /* MF Preamble Suppression */
+#define                MII_STATUS_ANC          0x0020  /* Auto-Negotiation Completed */
+#define                MII_STATUS_RF           0x0010  /* Remote Fault Detected */
+#define                MII_STATUS_ANA          0x0008  /* Auto-Negotiation Ability */
+#define                MII_STATUS_LS           0x0004  /* Link Up */
+#define                MII_STATUS_JD           0x0002  /* Jabber Condition Detected */
+#define                MII_STATUS_EC           0x0001  /* Ext Register Capabilities */
+#define MII_PHYID_H    0x2     /* PHY ID (high) */
+#define MII_PHYID_L    0x3     /* PHY ID (low) */
+#define MII_ANA                0x4     /* Auto-Negotiation Advertisement */
+#define                MII_ANA_NP      0x8000  /* Next PAge */
+#define                MII_ANA_RES     0x4000  /* Reserved */
+#define                MII_ANA_RF      0x2000  /* Remote Fault */
+#define                MII_ANA_TAF_M   0x1FE0  /* Technology Ability Field */
+#define                MII_ANA_TAF_S   5       /* Shift */
+#define                        MII_ANA_TAF_RES         0x1000  /* Reserved */
+#define                        MII_ANA_PAUSE_ASYM      0x0800  /* Asym. Pause */
+#define                        MII_ANA_PAUSE_SYM       0x0400  /* Sym. Pause */
+#define                        MII_ANA_100T4           0x0200  /* 100Base-T4 */
+#define                        MII_ANA_100TXFD         0x0100  /* 100Base-TX FD */
+#define                        MII_ANA_100TXHD         0x0080  /* 100Base-TX HD */
+#define                        MII_ANA_10TFD           0x0040  /* 10Base-T FD */
+#define                        MII_ANA_10THD           0x0020  /* 10Base-T HD */
+#define                MII_ANA_SEL_M   0x001F  /* Selector Field */
+#define                        MII_ANA_SEL_802_3 0x0001 /* 802.3 */
+#define MII_ANLPA      0x5     /* Auto-Neg Link Partner Ability Register */
+#define                MII_ANLPA_NP    0x8000  /* Next Page */
+#define                MII_ANLPA_ACK   0x4000  /* Acknowledge */
+#define                MII_ANLPA_RF    0x2000  /* Remote Fault */
+#define                MII_ANLPA_TAF_M 0x1FC0  /* Technology Ability Field */
+#define                MII_ANLPA_SEL_M 0x001F  /* Selector Field */
+#define MII_ANE                0x6     /* Auto-Negotiation Expansion */
+#define                MII_ANE_RES     0xFFE0  /* Reserved */
+#define                MII_ANE_PDF     0x0010  /* Parallel Detection Fault */
+#define                MII_ANE_LPNPA   0x0008  /* Link Partner is Next Page Able */
+#define                MII_ANE_NPA     0x0002  /* Local Device is Next Page Able */
+#define                MII_ANE_PR      0x0002  /* New Page has been received */
+#define                MII_ANE_LPANA   0x0001  /* Link Partner is Auto-Neg.able */
+#define MII_ANNPT      0x7     /* Auto-Negotiation Next Page Transmit */
+#define MII_ANLPRNP    0x8     /* Auto-Neg Link Partner Received Next Page */
+#define MII_1000_CTRL  0x9     /* 1000BASE-T Control Register */
+#define                MII_1000C_FULL  0x0200  /* Advertise 1000BASE-T full duplex */
+#define                MII_1000C_HALF  0x0100  /* Advertise 1000BASE-T half duplex */
+#define MII_1000_STATUS        0xA     /* 1000BASE-T Status Register */
+#define                MII_1000S_LRXOK 0x2000  /* Link partner local receiver status */
+#define                MII_1000S_RRXOK 0x1000  /* Link partner remote receiver status */
+#define                MII_1000S_FULL  0x0800  /* Link partner 1000BASE-T full duplex */
+#define                MII_1000S_HALF  0x0400  /* Link partner 1000BASE-T half duplex */
+/* 0xB ... 0xE */              /* Reserved */
+#define MII_EXT_STATUS 0xF     /* Extended Status */
+#define                MII_ESTAT_1000XFD       0x8000  /* 1000Base-X Full Duplex */
+#define                MII_ESTAT_1000XHD       0x4000  /* 1000Base-X Half Duplex */
+#define                MII_ESTAT_1000TFD       0x2000  /* 1000Base-T Full Duplex */
+#define                MII_ESTAT_1000THD       0x1000  /* 1000Base-T Half Duplex */
+#define                MII_ESTAT_RES           0x0FFF  /* Reserved */
+/* 0x10 ... 0x1F */            /* Vendor Specific */
index cd4e83c87434abeef2c5de175c3380f688ea4afb..d886cae7b69240378e25b186db7287916db1cc61 100644 (file)
@@ -465,6 +465,37 @@ driver osscore
        uid     0;
 };
 
+driver rtl8169
+{
+       system
+               UMAP            # 14
+               IRQCTL          # 19
+               DEVIO           # 21
+               #SDEVIO         # 22
+               SETALARM        # 24
+               TIMES           # 25
+               GETINFO         # 26
+               SAFECOPYFROM    # 31
+               SAFECOPYTO      # 32
+               SETGRANT        # 34
+               MAPDMA          # 41
+               PROFBUF         # 38
+               SYSCTL
+       ;
+       pci device      10ec/8129;
+       pci device      10ec/8167;
+       pci device      10ec/8169;
+       pci device      1186/4300;
+       pci device      1259/c107;
+       pci device      1385/8169;
+       pci device      16ec/0116;
+       pci device      1737/1032;
+       ipc
+               SYSTEM PM RS LOG TTY DS VM
+               pci inet amddev
+               ;
+};
+
 driver filter
 {
        system
index 390d3f06e893d59c12c27cd74e16a616dd4c6e55..0430f46e59900cf9adf0f4cb31d26518ee97de1a 100644 (file)
@@ -91,7 +91,7 @@ start)
     fi
 
     # start only network drivers that are in use
-    for driver in lance rtl8139 fxp dpeth dp8390 orinoco
+    for driver in lance rtl8139 rtl8169 fxp dpeth dp8390 orinoco
     do
         if grep " $driver " /etc/inet.conf > /dev/null  2>&1
         then