]> Zhao Yanbai Git Server - minix.git/commitdiff
Intel Pro/1000 driver written by Niek Linnenbank.
authorBen Gras <ben@minix3.org>
Mon, 7 Dec 2009 18:33:41 +0000 (18:33 +0000)
committerBen Gras <ben@minix3.org>
Mon, 7 Dec 2009 18:33:41 +0000 (18:33 +0000)
commands/scripts/netconf.sh
drivers/e1000/Makefile [new file with mode: 0644]
drivers/e1000/e1000.c [new file with mode: 0644]
drivers/e1000/e1000.h [new file with mode: 0644]
drivers/e1000/e1000_hw.h [new file with mode: 0644]
drivers/e1000/e1000_pci.h [new file with mode: 0644]
drivers/e1000/e1000_reg.h [new file with mode: 0644]
drivers/pci/pci_table.c
etc/drivers.conf
etc/usr/rc

index 29928c2061a589ce050b97f4d42db5303eba869b..e4c6c53be424786bf9d35a14198b3a62972d4407 100755 (executable)
@@ -103,10 +103,14 @@ cards()
            "1186:1340" "11DB:1234" "1259:A117" "1259:A11E" "126C:1211" \
            "13D1:AB06" "1432:9130" "14EA:AB06" "14EA:AB07" "1500:1360" \
            "1743:8139" "4033:1360"
-    card 4 "Realtek 8029 based card (also emulated by Qemu)" "10EC:8029"
-    card 5 "NE2000, 3com 503 or WD based card (also emulated by Bochs)"
-    card 6 "AMD LANCE (also emulated by VMWare and VirtualBox)" "1022:2000"
-    card 7 "Different Ethernet card (no networking)"
+    card 4 "Realtek 8169 based card"   \
+           "10EC:8129" "10EC:8167" "10EC:8169" "1186:4300" "1259:C107" \
+           "1385:8169" "16EC:0116" "1737:1032"
+    card 5 "Realtek 8029 based card (also emulated by Qemu)" "10EC:8029"
+    card 6 "NE2000, 3com 503 or WD based card (also emulated by Bochs)"
+    card 7 "AMD LANCE (also emulated by VMWare and VirtualBox)" "1022:2000"
+    card 8 "Intel PRO/1000 Gigabit" "8086:100E" "8086:107C" "8086:10CD"
+    card 9 "Different Ethernet card (no networking)"
 }
 
 warn()
@@ -143,15 +147,17 @@ drv_params()
           test "$v" = 1 && echo ""
            test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration."
                ;;
+       4) driver=rtl8169;  ;;
        3) driver=rtl8139;  ;;
-       4) driver=dp8390;   driverargs="dp8390_arg='DPETH0=pci'";       ;;
-       5) driver=dp8390;   driverargs="dp8390_arg='DPETH0=240:9'"; 
+       5) driver=dp8390;   driverargs="dp8390_arg='DPETH0=pci'";       ;;
+       6) driver=dp8390;   driverargs="dp8390_arg='DPETH0=240:9'"; 
           test "$v" = 1 && echo ""
            test "$v" = 1 && echo "Note: After installing, edit $LOCALRC to the right configuration."
            test "$v" = 1 && echo " chose option 4, the defaults for emulation by Bochs have been set."
                ;;
-        6) driver="lance"; ;;    
-        7) driver="psip0"; ;;    
+        7) driver="lance"; ;;    
+       8) driver="e1000"; ;;
+        9) driver="psip0"; ;;    
         *) warn "choose a number"
       esac
 }
diff --git a/drivers/e1000/Makefile b/drivers/e1000/Makefile
new file mode 100644 (file)
index 0000000..2d5506a
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Makefile for the Intel Pro/1000 driver.
+#
+DRIVER = e1000
+
+#
+# Directories.
+#
+u = /usr
+i = $u/include
+s = $i/sys
+m = $i/minix
+b = $i/ibm
+d = ..
+
+#
+# Build Programs, Flags and Variables.
+#
+CC      = exec cc
+CFLAGS  = -I$i $(CPROFILE)
+LDFLAGS = -i 
+LIBS    = -lsys -ltimers
+OBJ     = e1000.o
+
+# build local binary
+all build:     $(DRIVER)
+$(DRIVER):     $(OBJ) 
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+       install -S 128k $(DRIVER)
+
+# install with other drivers
+install:       /usr/sbin/$(DRIVER)
+/usr/sbin/$(DRIVER):   $(DRIVER)
+       install -o root -cs $? $@
+
+# clean up local files
+clean:
+       rm -f *.o $(DRIVER)
+
+depend: 
+       mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
diff --git a/drivers/e1000/e1000.c b/drivers/e1000/e1000.c
new file mode 100644 (file)
index 0000000..3e9c887
--- /dev/null
@@ -0,0 +1,1262 @@
+/**
+ * @file e1000.c
+ *
+ * @brief This file contains a device driver for Intel Pro/1000 
+ *        Gigabit Ethernet Controllers.
+ */
+
+#include "../drivers.h"
+#include <stdlib.h>
+#include <net/hton.h>
+#include <net/gen/ether.h>
+#include <net/gen/eth_io.h>
+#include <ibm/pci.h>
+#include <minix/ds.h>
+#include <minix/vm.h>
+#include <timers.h>
+#include "assert.h"
+#include "e1000.h"
+#include "e1000_hw.h"
+#include "e1000_reg.h"
+#include "e1000_pci.h"
+
+PRIVATE u16_t pcitab_e1000[] =
+{
+    E1000_DEV_ID_82540EM,
+    E1000_DEV_ID_82541GI_LF,
+    E1000_DEV_ID_ICH10_R_BM_LF,
+    0,
+};
+
+PRIVATE char *progname;
+PRIVATE e1000_t e1000_table[E1000_PORT_NR];
+
+_PROTOTYPE( PRIVATE int  e1000_init, (message *mp)                     );
+_PROTOTYPE( PRIVATE void e1000_init_pci, (void)                                );
+_PROTOTYPE( PRIVATE int  e1000_probe, (e1000_t *e)                     );
+_PROTOTYPE( PRIVATE int  e1000_init_hw, (e1000_t *e)                   );
+_PROTOTYPE( PRIVATE void e1000_init_addr, (e1000_t *e)                 );
+_PROTOTYPE( PRIVATE void e1000_init_buf,  (e1000_t *e)                 );
+_PROTOTYPE( PRIVATE void e1000_reset_hw, (e1000_t *e)                  );
+_PROTOTYPE( PRIVATE void e1000_writev_s, (message *mp, int from_int)   );
+_PROTOTYPE( PRIVATE void e1000_readv_s, (message *mp, int from_int)    );
+_PROTOTYPE( PRIVATE void e1000_getstat_s, (message *mp)                        );
+_PROTOTYPE( PRIVATE void e1000_getname, (message *mp)                  );
+_PROTOTYPE( PRIVATE void e1000_interrupt, (message *mp)                        );
+_PROTOTYPE( PRIVATE void e1000_signal, (void)                           );
+_PROTOTYPE( PRIVATE int  e1000_link_changed, (e1000_t *e)              );
+_PROTOTYPE( PRIVATE void e1000_report_link, (e1000_t *e)               );
+_PROTOTYPE( PRIVATE void e1000_stop, (void)                             );
+_PROTOTYPE( PRIVATE e1000_t * e1000_port, (int port)                    );
+_PROTOTYPE( PRIVATE uint32_t e1000_reg_read, (e1000_t *e, uint32_t reg) );
+_PROTOTYPE( PRIVATE void e1000_reg_write, (e1000_t *e, uint32_t reg,
+                                         uint32_t value)               );                                        
+_PROTOTYPE( PRIVATE void e1000_reg_set,   (e1000_t *e, uint32_t reg,
+                                         uint32_t value)               );
+_PROTOTYPE( PRIVATE void e1000_reg_unset, (e1000_t *e, uint32_t reg,
+                                          uint32_t value)              );
+_PROTOTYPE( PRIVATE u16_t eeprom_eerd, (void *e, int reg)              );
+_PROTOTYPE( PRIVATE u16_t eeprom_ich,  (void *e, int reg)              );
+_PROTOTYPE( PRIVATE int eeprom_ich_init, (e1000_t *e)                  );
+_PROTOTYPE( PRIVATE int eeprom_ich_cycle, (e1000_t *e, u32_t timeout)   );
+_PROTOTYPE( PRIVATE void reply, (e1000_t *e, int err, int may_block)   );
+_PROTOTYPE( PRIVATE void mess_reply, (message *req, message *reply)    );
+
+/*===========================================================================*
+ *                             main                                         *
+ *===========================================================================*/
+int main(int argc, char *argv[])
+{
+    message m;
+    int i, r;
+    u32_t tasknr;
+    e1000_t *e;
+    long v;
+
+    /* Verify command-line arguments. */
+    if (argc < 1)
+    {
+       panic("e1000", "no program name given in argc/argv", NO_NUM);
+    }
+    else
+       (progname = strrchr(argv[0],'/')) ? progname++ : (progname = argv[0]);
+
+    /* Clear state. */
+    memset(e1000_table, 0, sizeof(e1000_table));
+
+    /* Perform calibration. */
+    if((r = micro_delay_calibrate()) != OK)
+    {
+        panic("e1000", "rmicro_delay_calibrate failed", r);
+    }
+    /* Try to notify inet that we are present (again) */
+    if ((r = ds_retrieve_u32("inet", &tasknr)) == OK)
+    {
+        notify(tasknr);
+    }
+    else if (r != ESRCH)
+    {
+        printf("e1000: ds_retrieve_u32 failed for 'inet': %d\n", r);
+    }
+
+    /*
+     * Enter the main driver loop.
+     */
+    while (TRUE)
+    {
+       if ((r= receive(ANY, &m)) != OK)
+       {
+           panic("e1000", "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 HARDWARE:
+                   e1000_interrupt(&m);
+                   break;
+                
+               case PM_PROC_NR:
+                   e1000_signal();
+                   break;
+                
+               case CLOCK:
+                    break;
+           }
+           continue;
+       }
+       switch (m.m_type)
+       {
+           case DL_WRITEV_S:   e1000_writev_s(&m, FALSE);      break;
+           case DL_READV_S:    e1000_readv_s(&m, FALSE);       break;
+           case DL_CONF:       e1000_init(&m);                 break;
+           case DL_STOP:       e1000_stop();                   break;
+           case DL_GETSTAT_S:  e1000_getstat_s(&m);            break;
+           case DL_GETNAME:    e1000_getname(&m);              break;
+           default:
+               panic("e1000", "illegal message", m.m_type);
+       }
+    }
+}
+
+/*===========================================================================*
+ *                             e1000_init                                   *
+ *===========================================================================*/
+PRIVATE int e1000_init(mp)
+message *mp;
+{
+    static int first_time = 1;
+    message reply_mess;
+    e1000_t *e;
+
+    E1000_DEBUG(3, ("e1000: init()\n"));
+
+    /* Configure PCI devices, if needed. */
+    if (first_time)
+    {
+       first_time = 0;
+       e1000_init_pci(); 
+    }
+    /* Retrieve e1000 pointer. */
+    e = e1000_port(mp->DL_PORT);
+    e->client = mp->DL_PROC;
+
+    /* Initialize hardware, if needed. */
+    if (!(e->status & E1000_ENABLED) && !(e1000_init_hw(e)))
+    {
+        reply_mess.m_type = DL_CONF_REPLY;
+        reply_mess.m3_i1  = ENXIO;
+        mess_reply(mp, &reply_mess);
+        return;
+    }
+    /* Reply back to INET. */
+    reply_mess.m_type = DL_CONF_REPLY;
+    reply_mess.m3_i1  = mp->DL_PORT;
+    reply_mess.m3_i2  = E1000_PORT_NR;
+    *(ether_addr_t *) reply_mess.m3_ca1 = e->address;
+    mess_reply(mp, &reply_mess);
+}
+
+/*===========================================================================*
+ *                             e1000_int_pci                                *
+ *===========================================================================*/
+PRIVATE void e1000_init_pci()
+{
+    e1000_t *e;
+    int i;
+
+    /* Initialize the PCI bus. */
+    pci_init();
+
+    /* Try to detect e1000's. */
+    for (i = 0, e = &e1000_table[i]; i < E1000_PORT_NR; i++, e++)
+    {
+       strcpy(e->name, "e1000#0");
+       e->name[6] += i;        
+       e1000_probe(e);
+    }
+}
+
+/*===========================================================================*
+ *                             e1000_probe                                  *
+ *===========================================================================*/
+PRIVATE int e1000_probe(e)
+e1000_t *e;
+{
+    int i, r, devind;
+    u16_t vid, did;
+    u32_t status[2];
+    u32_t gfpreg, sector_base_addr, sector_end_addr;
+    char *dname, *str;
+
+    E1000_DEBUG(3, ("%s: probe()\n", e->name));
+
+    /*
+     * Attempt to iterate the PCI bus. Start at the beginning.
+     */
+    if ((r = pci_first_dev(&devind, &vid, &did)) == 0)
+    {
+       return FALSE;
+    }
+    /* Loop devices on the PCI bus. */
+    for(;;)
+    {
+       for (i = 0; pcitab_e1000[i] != 0; i++)
+       {
+           if (vid != 0x8086)
+               continue;
+       
+           if (did != pcitab_e1000[i])
+               continue;
+           else
+               break;
+       }
+       if (pcitab_e1000[i] != 0)
+           break;
+
+       if (!(r = pci_next_dev(&devind, &vid, &did)))
+       {
+           return FALSE;
+       }
+    }
+    /*
+     * Successfully detected an Intel Pro/1000 on the PCI bus.
+     */
+    e->status |= E1000_DETECTED;
+    e->eeprom_read = eeprom_eerd;
+    
+    /*
+     * Set card specific properties.
+     */
+    switch (did)
+    {
+        case E1000_DEV_ID_ICH10_R_BM_LF:
+            e->eeprom_read = eeprom_ich;
+            break;
+
+       case E1000_DEV_ID_82541GI_LF:
+           e->eeprom_done_bit = (1 << 1);
+           e->eeprom_addr_off =  2;
+           break;
+
+       default:
+           e->eeprom_done_bit = (1 << 4);
+           e->eeprom_addr_off =  8;
+           break;
+    }
+
+    /* Inform the user about the new card. */
+    if (!(dname = pci_dev_name(vid, did)))
+    {
+        dname = "Intel Pro/1000 Gigabit Ethernet Card";
+    }
+    E1000_DEBUG(1, ("%s: %s (%04x/%04x/%02x) at %s\n",
+                    e->name, dname, vid, did, e->revision, 
+                    pci_slot_name(devind)));
+
+    /* Reserve PCI resources found. */
+    if ((r = pci_reserve_ok(devind)) != OK)
+    {
+        panic("e1000", "failed to reserve PCI device", r);
+    }
+    /* Read PCI configuration. */
+    e->irq   = pci_attr_r8(devind, PCI_ILR);
+    e->regs  = vm_map_phys(SELF, (void *) pci_attr_r32(devind, PCI_BAR), 
+                          0x20000);
+                          
+    /* Verify mapped registers. */
+    if (e->regs == (u8_t *) -1)
+    {
+       panic("e1000", "failed to map hardware registers from PCI\n", 
+                       NO_NUM);
+    }
+    /* Optionally map flash memory. */
+    if (pci_attr_r32(devind, PCI_BAR_3))
+    {
+       e->flash = vm_map_phys(SELF, (void *) pci_attr_r32(devind, PCI_BAR_2),
+                              0x10000);
+
+       gfpreg = E1000_READ_FLASH_REG(e, ICH_FLASH_GFPREG);
+        /*
+         * sector_X_addr is a "sector"-aligned address (4096 bytes)
+         * Add 1 to sector_end_addr since this sector is included in
+         * the overall size.
+         */
+        sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
+        sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
+
+        /* flash_base_addr is byte-aligned */
+        e->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
+    }
+    /*
+     * Output debug information.
+     */
+    status[0] = e1000_reg_read(e, E1000_REG_STATUS);    
+    E1000_DEBUG(3, ("%s: MEM at 0x%lx, IRQ %d\n",
+                   e->name, e->regs, e->irq));
+    E1000_DEBUG(3, ("%s: link %s, %s duplex\n",
+                   e->name, status[0] & 3 ? "up"   : "down",
+                            status[0] & 1 ? "full" : "half"));
+    return TRUE;
+}
+
+/*===========================================================================*
+ *                             e1000_init_hw                                *
+ *===========================================================================*/
+PRIVATE int e1000_init_hw(e)
+e1000_t *e;
+{
+    int r, i;
+    u16_t word;
+
+    e->status  |= E1000_ENABLED;
+    e->irq_hook = e->irq;
+
+    /*
+     * Set the interrupt handler and policy. Do not automatically
+     * re-enable interrupts. Return the IRQ line number on interrupts.
+     */
+    if ((r = sys_irqsetpolicy(e->irq, 0, &e->irq_hook)) != OK)
+    {
+        panic(e->name, "sys_irqsetpolicy failed", r);
+    }
+    if ((r = sys_irqenable(&e->irq_hook)) != OK)
+    {
+       panic(e->name, "sys_irqenable failed", r);
+    }
+    /* Reset hardware. */
+    e1000_reset_hw(e);
+
+    /*
+     * Initialize appropriately, according to section 14.3 General Configuration
+     * of Intel's Gigabit Ethernet Controllers Software Developer's Manual.
+     */
+    e1000_reg_set(e,   E1000_REG_CTRL, E1000_REG_CTRL_ASDE | E1000_REG_CTRL_SLU);
+    e1000_reg_unset(e, E1000_REG_CTRL, E1000_REG_CTRL_LRST);
+    e1000_reg_unset(e, E1000_REG_CTRL, E1000_REG_CTRL_PHY_RST);
+    e1000_reg_unset(e, E1000_REG_CTRL, E1000_REG_CTRL_ILOS);
+    e1000_reg_write(e, E1000_REG_FCAL, 0);
+    e1000_reg_write(e, E1000_REG_FCAH, 0);
+    e1000_reg_write(e, E1000_REG_FCT,  0);
+    e1000_reg_write(e, E1000_REG_FCTTV, 0);
+    e1000_reg_unset(e, E1000_REG_CTRL, E1000_REG_CTRL_VME);
+
+    /* Clear Multicast Table Array (MTA). */
+    for (i = 0; i < 128; i++)
+    {
+       e1000_reg_write(e, E1000_REG_MTA + i, 0);
+    }
+    /* Initialize statistics registers. */
+    for (i = 0; i < 64; i++)
+    {
+       e1000_reg_write(e, E1000_REG_CRCERRS + (i * 4), 0);
+    }
+    /*
+     * Aquire MAC address and setup RX/TX buffers.
+     */
+    e1000_init_addr(e);
+    e1000_init_buf(e);
+    
+    /* Enable interrupts. */
+    e1000_reg_set(e,   E1000_REG_IMS, E1000_REG_IMS_LSC  |
+                                     E1000_REG_IMS_RXO  |
+                                     E1000_REG_IMS_RXT  |
+                                     E1000_REG_IMS_TXQE |
+                                     E1000_REG_IMS_TXDW);
+    return TRUE;
+}
+
+/*===========================================================================*
+ *                             e1000_init_addr                              *
+ *===========================================================================*/
+PRIVATE void e1000_init_addr(e)
+e1000_t *e;
+{
+    static char eakey[]= E1000_ENVVAR "#_EA";
+    static char eafmt[]= "x:x:x:x:x:x";
+    u16_t word;
+    int i;
+    long v;
+
+    /*
+     * Do we have a user defined ethernet address?
+     */
+    eakey[sizeof(E1000_ENVVAR)-1] = '0' + (e-e1000_table);
+
+    for (i= 0; i < 6; i++)
+    {
+        if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
+            break;
+       else
+           e->address.ea_addr[i]= v;
+    }
+    /*
+     * If that fails, read Ethernet Address from EEPROM.
+     */
+    if ((i != 0 && i != 6) || i == 0)
+    {
+       for (i = 0; i < 3; i++)
+       {
+           word = e->eeprom_read(e, i);
+           e->address.ea_addr[(i * 2)]     = (word & 0xff);
+           e->address.ea_addr[(i * 2) + 1] = (word & 0xff00) >> 8;
+       }
+    }
+    /*
+     * Set Receive Address.
+     */
+    e1000_reg_write(e, E1000_REG_RAL, *(u32_t *)(&e->address.ea_addr[0]));
+    e1000_reg_write(e, E1000_REG_RAH, *(u16_t *)(&e->address.ea_addr[4]));
+    e1000_reg_set(e,   E1000_REG_RAH,   E1000_REG_RAH_AV);
+    e1000_reg_set(e,   E1000_REG_RCTL,  E1000_REG_RCTL_MPE);
+
+    E1000_DEBUG(3, ("%s: Ethernet Address %x:%x:%x:%x:%x:%x\n", e->name,
+                   e->address.ea_addr[0], e->address.ea_addr[1],
+                   e->address.ea_addr[2], e->address.ea_addr[3],
+                   e->address.ea_addr[4], e->address.ea_addr[5]));
+}
+
+/*===========================================================================*
+ *                             e1000_init_buf                               *
+ *===========================================================================*/
+PRIVATE void e1000_init_buf(e)
+e1000_t *e;
+{
+    phys_bytes rx_desc_p, rx_buff_p;
+    phys_bytes tx_desc_p, tx_buff_p;
+    int i;
+
+    /* Number of descriptors. */
+    e->rx_desc_count = E1000_RXDESC_NR;
+    e->tx_desc_count = E1000_TXDESC_NR;
+
+    /*
+     * First, allocate the receive descriptors.
+     */
+    if (!e->rx_desc)
+    {
+       if ((e->rx_desc = alloc_contig(sizeof(e1000_rx_desc_t) * 
+                                      e->rx_desc_count, AC_ALIGN4K, 
+                                     &rx_desc_p)) == NULL)
+       {
+               panic(e->name, "failed to allocate RX descriptors", 
+                               NO_NUM);
+       }
+       memset(e->rx_desc, 0, sizeof(e1000_rx_desc_t) * e->rx_desc_count);
+
+       /*
+        * Allocate 2048-byte buffers.
+        */
+       e->rx_buffer_size = E1000_RXDESC_NR * E1000_IOBUF_SIZE;
+    
+       /* Attempt to allocate. */
+       if ((e->rx_buffer = alloc_contig(e->rx_buffer_size,
+                                        AC_ALIGN4K, &rx_buff_p)) == NULL)
+       {
+           panic(e->name, "failed to allocate RX buffers", NO_NUM);
+       }
+       /* Setup receive descriptors. */
+       for (i = 0; i < E1000_RXDESC_NR; i++)
+       {
+           e->rx_desc[i].buffer = rx_buff_p + (i * E1000_IOBUF_SIZE);
+       }
+    }
+    /*
+     * Then, allocate transmit descriptors.
+     */
+    if (!e->tx_desc)
+    {
+        if ((e->tx_desc = alloc_contig(sizeof(e1000_tx_desc_t) * 
+                                      e->tx_desc_count, AC_ALIGN4K, 
+                                     &tx_desc_p)) == NULL)
+       {
+               panic(e->name, "failed to allocate TX descriptors", 
+                               NO_NUM);
+       }
+       memset(e->tx_desc, 0, sizeof(e1000_tx_desc_t) * e->tx_desc_count);
+
+       /*
+        * Allocate 2048-byte buffers.
+        */
+       e->tx_buffer_size = E1000_TXDESC_NR * E1000_IOBUF_SIZE;
+    
+       /* Attempt to allocate. */
+       if ((e->tx_buffer = alloc_contig(e->tx_buffer_size,
+                                        AC_ALIGN4K, &tx_buff_p)) == NULL)
+       {
+           panic(e->name, "failed to allocate TX buffers", NO_NUM);
+       }
+       /* Setup transmit descriptors. */
+       for (i = 0; i < E1000_RXDESC_NR; i++)
+       {
+           e->tx_desc[i].buffer = tx_buff_p + (i * E1000_IOBUF_SIZE);
+       }
+    }
+    /*
+     * Setup the receive ring registers.
+     */
+    e1000_reg_write(e, E1000_REG_RDBAL, rx_desc_p);
+    e1000_reg_write(e, E1000_REG_RDBAH, 0);
+    e1000_reg_write(e, E1000_REG_RDLEN, e->rx_desc_count *
+                                       sizeof(e1000_rx_desc_t));
+    e1000_reg_write(e, E1000_REG_RDH,   0);
+    e1000_reg_write(e, E1000_REG_RDT,   e->rx_desc_count - 1);
+    e1000_reg_unset(e, E1000_REG_RCTL,  E1000_REG_RCTL_BSIZE);
+    e1000_reg_set(e,   E1000_REG_RCTL,  E1000_REG_RCTL_EN);
+    
+    /*
+     * Setup the transmit ring registers.
+     */
+    e1000_reg_write(e, E1000_REG_TDBAL, tx_desc_p);
+    e1000_reg_write(e, E1000_REG_TDBAH, 0);
+    e1000_reg_write(e, E1000_REG_TDLEN, e->tx_desc_count *
+                                       sizeof(e1000_tx_desc_t));
+    e1000_reg_write(e, E1000_REG_TDH,   0);
+    e1000_reg_write(e, E1000_REG_TDT,   0);
+    e1000_reg_set(  e, E1000_REG_TCTL,  E1000_REG_TCTL_EN | E1000_REG_TCTL_PSP);
+}
+
+/*===========================================================================*
+ *                             e1000_reset_hw                               *
+ *===========================================================================*/
+PRIVATE void e1000_reset_hw(e)
+e1000_t *e;
+{
+    /* Assert a Device Reset signal. */
+    e1000_reg_set(e, E1000_REG_CTRL, E1000_REG_CTRL_RST);
+
+    /* Wait one microsecond. */
+    tickdelay(1);
+}
+
+/*===========================================================================*
+ *                             e1000_writev_s                               *
+ *===========================================================================*/
+PRIVATE void e1000_writev_s(mp, from_int)
+message *mp;
+int from_int;
+{
+    e1000_t *e = e1000_port(mp->DL_PORT);
+    e1000_tx_desc_t *desc;
+    iovec_s_t iovec[E1000_IOVEC_NR];
+    int r, head, tail, i, bytes = 0, size;
+
+    E1000_DEBUG(3, ("e1000: writev_s(%x,%d)\n", mp, from_int));
+
+    /* Are we called from the interrupt handler? */
+    if (!from_int)
+    {
+       /* We cannot write twice simultaneously. 
+       assert(!(e->status & E1000_WRITING)); */
+    
+       /* Copy write message. */
+       e->tx_message = *mp;
+       e->status |= E1000_WRITING;
+
+       /* Must be a sane vector count. */
+       assert(e->tx_message.DL_COUNT > 0);
+       assert(e->tx_message.DL_COUNT < E1000_IOVEC_NR);
+
+       /*
+        * Copy the I/O vector table.
+        */
+       if ((r = sys_safecopyfrom(e->client, e->tx_message.DL_GRANT, 0,
+                                 (vir_bytes) iovec, e->tx_message.DL_COUNT *
+                                 sizeof(iovec_s_t), D)) != OK)
+       {
+           panic(e->name, "sys_safecopyfrom() failed", r);
+       }
+       /* Find the head, tail and current descriptors. */
+       head =  e1000_reg_read(e, E1000_REG_TDH);
+       tail =  e1000_reg_read(e, E1000_REG_TDT);
+       desc = &e->tx_desc[tail];
+       
+       E1000_DEBUG(4, ("%s: head=%d, tail=%d\n",
+                        e->name, head, tail));
+
+       /* Loop vector elements. */
+       for (i = 0; i < e->tx_message.DL_COUNT; i++)
+       {
+           size = iovec[i].iov_size < (E1000_IOBUF_SIZE - bytes) ?
+                  iovec[i].iov_size : (E1000_IOBUF_SIZE - bytes);
+
+           E1000_DEBUG(4, ("iovec[%d] = %d\n", i, size));
+
+           /* Copy bytes to TX queue buffers. */
+           if ((r = sys_safecopyfrom(e->client, iovec[i].iov_grant, 0,
+                                    (vir_bytes) e->tx_buffer +
+                                    (tail * E1000_IOBUF_SIZE),
+                                     size, D)) != OK)
+           {
+               panic(e->name, "sys_safecopyfrom() failed", r);
+           }
+           /* Mark this descriptor ready. */
+           desc->status  = 0;
+           desc->command = 0;
+           desc->length  = size;
+
+           /* Marks End-of-Packet. */
+           if (i == e->tx_message.DL_COUNT - 1)
+           {
+               desc->command = E1000_TX_CMD_EOP |
+                               E1000_TX_CMD_FCS |
+                               E1000_TX_CMD_RS;
+           }
+           /* Move to next descriptor. */
+           tail   = (tail + 1) % e->tx_desc_count;
+           bytes +=  size;
+            desc   = &e->tx_desc[tail];
+       }
+       /* Increment tail. Start transmission. */
+       e1000_reg_write(e, E1000_REG_TDT,  tail);
+
+       E1000_DEBUG(2, ("e1000: wrote %d byte packet\n", bytes));
+    }
+    else
+    {
+       e->status |= E1000_TRANSMIT;
+    }
+    reply(e, OK, FALSE);
+}
+
+/*===========================================================================*
+ *                             e1000_readv_s                                *
+ *===========================================================================*/
+PRIVATE void e1000_readv_s(mp, from_int)
+message *mp;
+int from_int;
+{
+    e1000_t *e = e1000_port(mp->DL_PORT);
+    e1000_rx_desc_t *desc;
+    iovec_s_t iovec[E1000_IOVEC_NR];
+    int i, r, head, tail, cur, bytes = 0, size;
+
+    E1000_DEBUG(3, ("e1000: readv_s(%x,%d)\n", mp, from_int));
+
+    /* Are we called from the interrupt handler? */
+    if (!from_int)
+    {
+       e->rx_message = *mp;
+       e->status    |= E1000_READING;
+       e->rx_size    = 0;
+       
+       assert(e->rx_message.DL_COUNT > 0);
+       assert(e->rx_message.DL_COUNT < E1000_IOVEC_NR);
+    }
+    if (e->status & E1000_READING)
+    {
+       /*
+        * Copy the I/O vector table first.
+        */
+       if ((r = sys_safecopyfrom(e->client, e->rx_message.DL_GRANT, 0,
+                                 (vir_bytes) iovec, e->rx_message.DL_COUNT *
+                                 sizeof(iovec_s_t), D)) != OK)
+       {
+           panic(e->name, "sys_safecopyfrom() failed", r);
+       }
+       /* Find the head, tail and current descriptors. */
+       head = e1000_reg_read(e, E1000_REG_RDH);
+       tail = e1000_reg_read(e, E1000_REG_RDT);
+       cur  = (tail + 1) % e->rx_desc_count;
+       desc = &e->rx_desc[cur];
+       
+       /*
+        * Only handle one packet at a time.
+        */
+       if (!(desc->status & E1000_RX_STATUS_EOP))
+       {
+           reply(e, OK, FALSE);
+           return;
+       }
+       E1000_DEBUG(4, ("%s: head=%x, tail=%d\n",
+                         e->name, head, tail));
+
+       /*
+        * Copy to vector elements.
+        */    
+       for (i = 0; i < e->rx_message.DL_COUNT && bytes < desc->length; i++)
+       {
+           size = iovec[i].iov_size < (desc->length - bytes) ?
+                  iovec[i].iov_size : (desc->length - bytes);
+       
+           E1000_DEBUG(4, ("iovec[%d] = %d[%d]\n",
+                         i, iovec[i].iov_size, size));
+
+           if ((r = sys_safecopyto(e->client, iovec[i].iov_grant, 0,
+                                  (vir_bytes) e->rx_buffer + bytes + 
+                                  (cur * E1000_IOBUF_SIZE),
+                                   size, D)) != OK)
+           {
+               panic(e->name, "sys_safecopyto() failed", r);
+           }
+           bytes += size;
+       }
+       desc->status = 0;
+
+       /*
+        * Update state.
+        */
+       e->rx_size   = bytes;
+       e->status   |= E1000_RECEIVED;
+       E1000_DEBUG(2, ("e1000: got %d byte packet\n", e->rx_size));
+
+       /* Increment tail. */
+       e1000_reg_write(e, E1000_REG_RDT, (tail + 1) % e->rx_desc_count);
+    }
+    reply(e, OK, FALSE);
+}
+
+/*===========================================================================*
+ *                             e1000_getstat_s                              *
+ *===========================================================================*/
+PRIVATE void e1000_getstat_s(mp)
+message *mp;
+{
+    int r;
+    eth_stat_t stats;
+    e1000_t *e = e1000_port(mp->DL_PORT);
+
+    E1000_DEBUG(3, ("e1000: getstat_s()\n"));
+
+    stats.ets_recvErr   = e1000_reg_read(e, E1000_REG_RXERRC);
+    stats.ets_sendErr   = 0;
+    stats.ets_OVW       = 0;
+    stats.ets_CRCerr    = e1000_reg_read(e, E1000_REG_CRCERRS);
+    stats.ets_frameAll  = 0;
+    stats.ets_missedP   = e1000_reg_read(e, E1000_REG_MPC);
+    stats.ets_packetR   = e1000_reg_read(e, E1000_REG_TPR);
+    stats.ets_packetT   = e1000_reg_read(e, E1000_REG_TPT);
+    stats.ets_collision = e1000_reg_read(e, E1000_REG_COLC);
+    stats.ets_transAb   = 0;
+    stats.ets_carrSense = 0;
+    stats.ets_fifoUnder = 0;
+    stats.ets_fifoOver  = 0;
+    stats.ets_CDheartbeat = 0;
+    stats.ets_OWC = 0;
+
+    sys_safecopyto(mp->DL_PROC, mp->DL_GRANT, 0, (vir_bytes)&stats,
+                   sizeof(stats), D);
+    mp->m_type  = DL_STAT_REPLY;
+    mp->DL_PORT = mp->DL_PORT;
+    mp->DL_STAT = OK;
+    if((r=send(mp->m_source, mp)) != OK)
+       panic("e1000", "e1000_getstat: send() failed", r);
+}
+
+/*===========================================================================*
+ *                             e1000_getname                                *
+ *===========================================================================*/
+PRIVATE void e1000_getname(mp)
+message *mp;
+{
+    int r;
+
+    E1000_DEBUG(3, ("e1000: getname()\n"));
+
+    /* Copy our program name. */
+    strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
+    mp->DL_NAME[ sizeof(mp->DL_NAME) - 1 ] = 0;
+
+    /* Acknowledge the name request. */
+    mp->m_type = DL_NAME_REPLY;
+    if ((r = send(mp->m_source, mp)) != OK)
+    {
+       panic("e1000", "e1000_getname: send() failed", r);
+    }
+}
+
+/*===========================================================================*
+ *                             e1000_interrupt                              *
+ *===========================================================================*/
+PRIVATE void e1000_interrupt(mp)
+message *mp;
+{
+    e1000_t *e;
+    u32_t cause;
+    unsigned int i;
+
+    E1000_DEBUG(3, ("e1000: interrupt\n"));
+
+    /*
+     * Loop all cards. Check for interrupt reason(s).
+     */
+    for (i = 0; i < E1000_PORT_NR; i++)
+    {
+       e = e1000_port(i);
+       
+        /* Re-enable interrupts. */
+        if (sys_irqenable(&e->irq_hook) != OK)
+        {
+           panic("e1000", "failed to re-enable IRQ", NO_NUM);
+        }
+
+       /* Read the Interrupt Cause Read register. */
+        if ((cause = e1000_reg_read(e, E1000_REG_ICR)))
+        {
+           if (cause & E1000_REG_ICR_LSC)
+               e1000_link_changed(e);
+
+           if (cause & (E1000_REG_ICR_RXO | E1000_REG_ICR_RXT))
+               e1000_readv_s(&e->rx_message, TRUE);
+       
+           if ((cause & E1000_REG_ICR_TXQE) ||
+               (cause & E1000_REG_ICR_TXDW))
+               e1000_writev_s(&e->tx_message, TRUE);
+
+       }
+    }
+}
+
+/*===========================================================================*
+ *                             e1000_signal                                 *
+ *===========================================================================*/
+PRIVATE void e1000_signal(void)
+{
+    sigset_t sigset;
+    int sig;
+
+    E1000_DEBUG(3, ("e1000: signal()\n"));
+
+    /* Try to obtain signal set from PM. */
+    if (getsigset(&sigset) != 0)
+    {
+        return;
+    }
+    /* Check for known signals. */
+    if (sigismember(&sigset, SIGTERM))
+    {
+       e1000_stop();
+    }
+}
+
+/*===========================================================================*
+ *                             e1000_link_changed                           *
+ *===========================================================================*/
+PRIVATE int e1000_link_changed(e)
+e1000_t *e;
+{
+    E1000_DEBUG(4, ("%s: link_changed()\n", e->name));
+    return FALSE;
+}
+
+/*===========================================================================*
+ *                             e1000_report_link                            *
+ *===========================================================================*/
+PRIVATE void e1000_report_link(e)
+e1000_t *e;
+{
+    E1000_DEBUG(4, ("%s: report_link()\n", e->name));
+}
+
+/*===========================================================================*
+ *                             e1000_stop                                   *
+ *===========================================================================*/
+PRIVATE void e1000_stop()
+{
+    E1000_DEBUG(3, ("e1000: stop()\n"));
+    exit(EXIT_SUCCESS);
+}
+
+/*===========================================================================*
+ *                             e1000_port                                   *
+ *===========================================================================*/
+PRIVATE e1000_t * e1000_port(num)
+int num;
+{
+    /*
+     * Is the given port number within the allowed range?
+     */
+    if (num < 0 || num >= E1000_PORT_NR)
+    {
+       panic("e1000", "invalid port number given", num);
+    }
+
+    /*
+     * The card must be active.
+     */
+    if (!(e1000_table[num].status & E1000_DETECTED))
+    {
+       panic("e1000", "inactive port number given", num);
+    }
+    return &e1000_table[num];
+}
+
+
+/*===========================================================================*
+ *                             e1000_reg_read                               *
+ *===========================================================================*/
+PRIVATE uint32_t e1000_reg_read(e, reg)
+e1000_t *e;
+uint32_t reg;
+{
+    uint32_t value;
+
+    /* Assume a sane register. */
+    assert(reg < 0x1ffff);
+
+    /* Read from memory mapped register. */
+    value = *(u32_t *)(e->regs + reg);
+
+    /* Return the result. */    
+    return value;
+}
+
+/*===========================================================================*
+ *                             e1000_reg_write                              *
+ *===========================================================================*/
+PRIVATE void e1000_reg_write(e, reg, value)
+e1000_t *e;
+uint32_t reg;
+uint32_t value;
+{
+    /* Assume a sane register. */
+    assert(reg < 0x1ffff);
+    
+    /* Write to memory mapped register. */
+    *(u32_t *)(e->regs + reg) = value;
+}
+
+/*===========================================================================*
+ *                             e1000_reg_set                                *
+ *===========================================================================*/
+PRIVATE void e1000_reg_set(e, reg, value)
+e1000_t *e;
+uint32_t reg;
+uint32_t value;
+{
+    uint32_t data;
+
+    /* First read the current value. */
+    data = e1000_reg_read(e, reg);
+    
+    /* Set value, and write back. */
+    e1000_reg_write(e, reg, data | value);
+}
+
+/*===========================================================================*
+ *                             e1000_reg_unset                              *
+ *===========================================================================*/
+PRIVATE void e1000_reg_unset(e, reg, value)
+e1000_t *e;
+uint32_t reg;
+uint32_t value;
+{
+    uint32_t data;
+
+    /* First read the current value. */
+    data = e1000_reg_read(e, reg);
+    
+    /* Unset value, and write back. */
+    e1000_reg_write(e, reg, data & ~value);
+}
+
+
+/*===========================================================================*
+ *                             eeprom_eerd                                  *
+ *===========================================================================*/
+PRIVATE u16_t eeprom_eerd(v, reg)
+void *v;
+int reg;
+{
+    e1000_t *e = (e1000_t *) v;
+    u16_t data;
+
+    /* Request EEPROM read. */
+    e1000_reg_write(e, E1000_REG_EERD,
+                  (reg << e->eeprom_addr_off) | (E1000_REG_EERD_START));
+
+    /* Wait until ready. */
+    while (!(e1000_reg_read(e, E1000_REG_EERD) &
+                              e->eeprom_done_bit));
+
+    /* Fetch data. */
+    data = (e1000_reg_read(e, E1000_REG_EERD) &
+                             E1000_REG_EERD_DATA) >> 16;
+    return data;
+}
+
+/*===========================================================================* 
+ *                              eeprom_ich_init                              * 
+ *===========================================================================*/
+PRIVATE int eeprom_ich_init(e)
+e1000_t *e;
+{
+    union ich8_hws_flash_status hsfsts;
+    int ret_val = -1;
+    int i = 0;
+
+    hsfsts.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFSTS);
+
+    /* Check if the flash descriptor is valid */
+    if (hsfsts.hsf_status.fldesvalid == 0)
+    {
+        E1000_DEBUG(3, ("Flash descriptor invalid.  "
+                       "SW Sequencing must be used."));
+        goto out;                                                         
+    }                                                                         
+    /* Clear FCERR and DAEL in hw status by writing 1 */                      
+    hsfsts.hsf_status.flcerr = 1;                                             
+    hsfsts.hsf_status.dael   = 1;                                     
+                                                                        
+    E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFSTS, hsfsts.regval);   
+                                                                        
+    /*                                                              
+     * Either we should have a hardware SPI cycle in progress       
+     * bit to check against, in order to start a new cycle or       
+     * FDONE bit should be changed in the hardware so that it 
+     * is 1 after hardware reset, which can then be used as an 
+     * indication whether a cycle is in progress or has been 
+     * completed. 
+     */                                                                
+    if (hsfsts.hsf_status.flcinprog == 0)
+    {
+        /* 
+         * There is no cycle running at present, 
+         * so we can start a cycle. 
+         * Begin by setting Flash Cycle Done. 
+         */
+        hsfsts.hsf_status.flcdone = 1;
+        E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFSTS, hsfsts.regval);
+       ret_val = 0;
+    }
+    else
+    {
+        /* 
+         * Otherwise poll for sometime so the current 
+         * cycle has a chance to end before giving up. 
+         */
+        for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++)
+       {
+            hsfsts.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFSTS);
+            
+           if (hsfsts.hsf_status.flcinprog == 0)
+           {
+                ret_val = 0;
+                break;
+            }
+            tickdelay(1);
+        }
+        if (ret_val == 0)
+       {
+            /* 
+             * Successful in waiting for previous cycle to timeout, 
+             * now set the Flash Cycle Done. 
+             */
+            hsfsts.hsf_status.flcdone = 1;
+            E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFSTS,
+                                    hsfsts.regval);
+        }
+       else
+       {
+            E1000_DEBUG(3, ("Flash controller busy, cannot get access"));
+        }
+    }
+out:    
+    return ret_val;
+}
+
+/*===========================================================================* 
+ *                              eeprom_ich_cycle                             * 
+ *===========================================================================*/
+PRIVATE int eeprom_ich_cycle(e1000_t *e, u32_t timeout)
+{
+    union ich8_hws_flash_ctrl hsflctl;
+    union ich8_hws_flash_status hsfsts;
+    int ret_val = -1;
+    u32_t i = 0;
+
+    E1000_DEBUG(3, ("e1000_flash_cycle_ich8lan"));
+
+    /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
+    hsflctl.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFCTL);
+    hsflctl.hsf_ctrl.flcgo = 1;
+    E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFCTL, hsflctl.regval);
+                
+    /* wait till FDONE bit is set to 1 */
+    do
+    {
+        hsfsts.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFSTS);
+        if (hsfsts.hsf_status.flcdone == 1)
+            break;
+        tickdelay(1);
+    }
+    while (i++ < timeout);
+                                                              
+    if (hsfsts.hsf_status.flcdone == 1 && hsfsts.hsf_status.flcerr == 0)
+        ret_val = 0;
+                                
+    return ret_val;
+}
+
+/*===========================================================================*
+ *                             eeprom_ich                                   *
+ *===========================================================================*/
+PRIVATE u16_t eeprom_ich(v, reg)
+void *v;
+int reg;
+{
+    union ich8_hws_flash_status hsfsts;
+    union ich8_hws_flash_ctrl hsflctl;
+    u32_t flash_linear_addr;
+    u32_t flash_data = 0;
+    int ret_val = -1;
+    u8_t count = 0;
+    e1000_t *e = (e1000_t *) v;
+    u16_t data;
+                        
+    E1000_DEBUG(3, ("e1000_read_flash_data_ich8lan"));
+                                         
+    if (reg > ICH_FLASH_LINEAR_ADDR_MASK)
+        goto out;
+
+    reg *= sizeof(u16_t);                
+    flash_linear_addr = (ICH_FLASH_LINEAR_ADDR_MASK & reg) +
+                         e->flash_base_addr;
+
+    do {
+       tickdelay(1);
+        
+       /* Steps */
+        ret_val = eeprom_ich_init(e);
+        if (ret_val != 0)
+            break;
+
+        hsflctl.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFCTL);
+        /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
+        hsflctl.hsf_ctrl.fldbcount = 1;
+        hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
+        E1000_WRITE_FLASH_REG16(e, ICH_FLASH_HSFCTL, hsflctl.regval);
+        E1000_WRITE_FLASH_REG(e, ICH_FLASH_FADDR, flash_linear_addr);
+
+        ret_val = eeprom_ich_cycle(v, ICH_FLASH_READ_COMMAND_TIMEOUT);
+        
+        /* 
+         * Check if FCERR is set to 1, if set to 1, clear it 
+         * and try the whole sequence a few more times, else 
+         * read in (shift in) the Flash Data0, the order is 
+         * least significant byte first msb to lsb 
+         */
+        if (ret_val == 0)
+       {
+            flash_data = E1000_READ_FLASH_REG(e, ICH_FLASH_FDATA0);
+            data = (u16_t)(flash_data & 0x0000FFFF);
+            break;
+        }
+       else
+       {
+            /* 
+             * If we've gotten here, then things are probably 
+             * completely hosed, but if the error condition is 
+            * detected, it won't hurt to give it another try... 
+             * ICH_FLASH_CYCLE_REPEAT_COUNT times. 
+             */
+            hsfsts.regval = E1000_READ_FLASH_REG16(e, ICH_FLASH_HSFSTS);
+            
+           if (hsfsts.hsf_status.flcerr == 1)
+           {
+                /* Repeat for some time before giving up. */
+                continue;
+            }
+           else if (hsfsts.hsf_status.flcdone == 0)
+           {
+                E1000_DEBUG(3, ("Timeout error - flash cycle "
+                               "did not complete."));
+                break;
+            }
+        }
+    } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
+
+out:
+    return data;
+}
+
+/*===========================================================================*
+ *                             reply                                        *
+ *===========================================================================*/
+PRIVATE void reply(e, err, may_block)
+e1000_t *e;
+int err;
+int may_block;
+{
+    message msg;
+    int r;
+
+    /* Only reply to client for read/write request. */
+    if (!(e->status & E1000_READING ||
+          e->status & E1000_WRITING))
+    {
+       return;
+    }
+    /* Construct reply message. */
+    msg.m_type   = DL_TASK_REPLY;
+    msg.DL_PORT  = e - e1000_table;
+    msg.DL_PROC  = e->client;
+    msg.DL_COUNT = 0;
+    msg.DL_STAT  = 0;
+    msg.DL_CLCK  = 0;
+
+    /* Did we successfully receive packet(s)? */
+    if (e->status & E1000_READING &&
+       e->status & E1000_RECEIVED)
+    {
+       msg.DL_STAT  = DL_PACK_RECV;
+       msg.DL_COUNT = e->rx_size >= ETH_MIN_PACK_SIZE ?
+                      e->rx_size  : ETH_MIN_PACK_SIZE;
+
+        /* Clear flags. */
+       e->status &= ~(E1000_READING | E1000_RECEIVED);
+    }
+    /* Did we successfully transmit packet(s)? */
+    if (e->status & E1000_TRANSMIT &&
+        e->status & E1000_WRITING)
+    {
+       msg.DL_STAT  = DL_PACK_SEND;
+       msg.DL_COUNT = 0;
+       
+       /* Clear flags. */
+       e->status &= ~(E1000_WRITING | E1000_TRANSMIT);
+    }
+
+    /* Acknowledge to INET. */
+    if ((r = send(e->client, &msg)) != OK)
+    {
+        panic("e1000", "send() failed", r);
+    }
+}
+
+/*===========================================================================*
+ *                             mess_reply                                   *
+ *===========================================================================*/
+PRIVATE void mess_reply(req, reply_mess)
+message *req;
+message *reply_mess;
+{
+    if (send(req->m_source, reply_mess) != OK)
+    {
+        panic("e1000", "unable to send reply message", NO_NUM);
+    }
+}
diff --git a/drivers/e1000/e1000.h b/drivers/e1000/e1000.h
new file mode 100644 (file)
index 0000000..bf4da4b
--- /dev/null
@@ -0,0 +1,177 @@
+/**
+ * @file e1000.h
+ *
+ * @brief Device driver implementation declarations for the
+ *        Intel Pro/1000 Gigabit Ethernet card(s).
+ *
+ * Parts of this code is based on the DragonflyBSD (FreeBSD)
+ * implementation, and the fxp driver for Minix 3.
+ *
+ * @see http://svn.freebsd.org/viewvc/base/head/sys/dev/e1000/
+ * @see fxp.c
+ *
+ * @author Niek Linnenbank <nieklinnenbank@gmail.com>
+ * @date September 2009
+ *
+ */
+
+#ifndef __E1000_H
+#define __E1000_H
+
+#include "../drivers.h" 
+#include <stdlib.h> 
+#include <net/hton.h> 
+#include <net/gen/ether.h> 
+#include <net/gen/eth_io.h> 
+#include <ibm/pci.h> 
+#include <minix/ds.h> 
+#include "e1000_hw.h"
+
+/**
+ * @name Constants.
+ * @{
+ */
+
+/** Maximum number of cards supported. */
+#define E1000_PORT_NR 1
+
+/** Number of receive descriptors per card. */
+#define E1000_RXDESC_NR 256
+
+/** Number of transmit descriptors per card. */
+#define E1000_TXDESC_NR 256
+
+/** Number of I/O vectors to use. */
+#define E1000_IOVEC_NR 16
+
+/** Size of each I/O buffer per descriptor. */
+#define E1000_IOBUF_SIZE 2048
+
+/** Debug verbosity. */
+#define E1000_VERBOSE 1
+
+/** MAC address override variable. */
+#define E1000_ENVVAR "E1000ETH"
+
+/**
+ * @}
+ */
+
+/**
+ * @name Status Flags.
+ * @{
+ */
+
+/** Card has been detected on the PCI bus. */
+#define E1000_DETECTED (1 << 0)
+
+/** Card is enabled. */
+#define E1000_ENABLED  (1 << 1)
+
+/** Client has requested to receive packets. */
+#define E1000_READING  (1 << 2)
+
+/** Client has requested to write packets. */
+#define E1000_WRITING  (1 << 3)
+
+/** Received some packets on the card. */
+#define E1000_RECEIVED (1 << 4)
+
+/** Transmitted some packets on the card. */
+#define E1000_TRANSMIT (1 << 5)
+
+/**
+ * @}
+ */
+
+/**
+ * @name Macros.
+ * @{
+ */
+
+/**
+ * @brief Print a debug message.
+ * @param level Debug verbosity level.
+ * @param args Arguments to printf().
+ */
+#define E1000_DEBUG(level, args) \
+       if ((level) <= E1000_VERBOSE) \
+       { \
+           printf args; \
+       } \
+
+/**
+ * Read a byte from flash memory.
+ * @param e e1000_t pointer.
+ * @param reg Register offset.
+ */
+#define E1000_READ_FLASH_REG(e,reg) \
+    *(u32_t *) (((e)->flash) + (reg))
+
+/**
+ * Read a 16-bit word from flash memory.
+ * @param e e1000_t pointer.
+ * @param reg Register offset.
+ */
+#define E1000_READ_FLASH_REG16(e,reg) \
+    *(u16_t *) (((e)->flash) + (reg))
+
+/**
+ * Write a 16-bit word to flash memory.
+ * @param e e1000_t pointer.
+ * @param reg Register offset.
+ * @param value New value.
+ */
+#define E1000_WRITE_FLASH_REG(e,reg,value) \
+    *((u32_t *) (((e)->flash) + (reg))) = (value)
+
+/**
+ * Write a 16-bit word to flash memory.
+ * @param e e1000_t pointer.
+ * @param reg Register offset.
+ * @param value New value.
+ */
+#define E1000_WRITE_FLASH_REG16(e,reg,value) \
+    *((u16_t *) (((e)->flash) + (reg))) = (value)
+
+/**
+ * @}
+ */
+
+/**
+ * @brief Describes the state of an Intel Pro/1000 card.
+ */
+typedef struct e1000
+{
+    char name[8];                /**< String containing the device name. */    
+    int status;                          /**< Describes the card's current state. */
+    int irq;                     /**< Interrupt Request Vector. */
+    int irq_hook;                 /**< Interrupt Request Vector Hook. */
+    int revision;                /**< Hardware Revision Number. */
+    u8_t *regs;                          /**< Memory mapped hardware registers. */
+    u8_t *flash;                 /**< Optional flash memory. */
+    u32_t flash_base_addr;       /**< Flash base address. */
+    ether_addr_t address;        /**< Ethernet MAC address. */
+    u16_t (*eeprom_read)(void *, int reg); /**< Function to read  
+                                                the EEPROM. */
+    int eeprom_done_bit;         /**< Offset of the EERD.DONE bit. */    
+    int eeprom_addr_off;         /**< Offset of the EERD.ADDR field. */
+
+    e1000_rx_desc_t *rx_desc;    /**< Receive Descriptor table. */
+    int rx_desc_count;           /**< Number of Receive Descriptors. */
+    char *rx_buffer;             /**< Receive buffer returned by malloc(). */
+    int rx_buffer_size;                  /**< Size of the receive buffer. */
+
+    e1000_tx_desc_t *tx_desc;    /**< Transmit Descriptor table. */
+    int tx_desc_count;           /**< Number of Transmit Descriptors. */
+    char *tx_buffer;             /**< Transmit buffer returned by malloc(). */
+    int tx_buffer_size;                  /**< Size of the transmit buffer. */
+
+    int client;                   /**< Process ID being served by e1000. */
+    message rx_message;                  /**< Read message received from client. */
+    message tx_message;                  /**< Write message received from client. */
+    size_t rx_size;              /**< Size of one packet received. */
+}
+e1000_t;
+
+#endif /* __E1000_H */
diff --git a/drivers/e1000/e1000_hw.h b/drivers/e1000/e1000_hw.h
new file mode 100644 (file)
index 0000000..42740a3
--- /dev/null
@@ -0,0 +1,174 @@
+/**
+ * @file e1000.h
+ *
+ * @brief Hardware specific datastructures of the Intel
+ *        Pro/1000 Gigabit Ethernet card(s).
+ *
+ * Parts of this code is based on the DragonflyBSD (FreeBSD)
+ * implementation, and the fxp driver for Minix 3.
+ *
+ * @see http://svn.freebsd.org/viewvc/base/head/sys/dev/e1000/
+ * @see fxp.c
+ *
+ * @author Niek Linnenbank <nieklinnenbank@gmail.com>
+ * @date September 2009
+ *
+ */
+
+#ifndef __E1000_HW_H
+#define __E1000_HW_H
+
+#include <stdint.h>
+
+/**
+ * @name Datastructures.
+ * @{
+ */
+
+/**
+ * @brief Receive Descriptor Format.
+ */
+typedef struct e1000_rx_desc
+{
+    u32_t buffer;      /**< Address of the receive data buffer (64-bit). */
+    u32_t buffer_h;     /**< High 32-bits of the receive data buffer (unused). */
+    u16_t length;      /**< Size of the receive buffer. */
+    u16_t checksum;    /**< Packet checksum. */
+    u8_t  status;      /**< Descriptor status. */
+    u8_t  errors;      /**< Descriptor errors. */
+    u16_t special;     /**< VLAN information. */    
+}
+e1000_rx_desc_t;
+
+/**
+ * @brief Transmit Descriptor Format.
+ */
+typedef struct e1000_tx_desc
+{
+    u32_t buffer;      /**< Address of the transmit buffer (64-bit). */
+    u32_t buffer_h;    /**< High 32-bits of the transmit buffer (unused). */
+    u16_t length;      /**< Size of the transmit buffer contents. */
+    u8_t  checksum_off; /**< Checksum Offset. */
+    u8_t  command;     /**< Command field. */
+    u8_t  status;      /**< Status field. */
+    u8_t  checksum_st;  /**< Checksum Start. */
+    u16_t special;     /**< Optional special bits. */
+}
+e1000_tx_desc_t;
+
+/**
+ * @brief ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown.
+ * @see http://gitweb.dragonflybsd.org
+ */
+union ich8_hws_flash_status
+{
+    struct ich8_hsfsts
+    {
+        unsigned flcdone    :1; /**< bit 0 Flash Cycle Done */
+        unsigned flcerr     :1; /**< bit 1 Flash Cycle Error */
+        unsigned dael       :1; /**< bit 2 Direct Access error Log */
+        unsigned berasesz   :2; /**< bit 4:3 Sector Erase Size */
+        unsigned flcinprog  :1; /**< bit 5 flash cycle in Progress */
+        unsigned reserved1  :2; /**< bit 13:6 Reserved */
+        unsigned reserved2  :6; /**< bit 13:6 Reserved */
+        unsigned fldesvalid :1; /**< bit 14 Flash Descriptor Valid */
+        unsigned flockdn    :1; /**< bit 15 Flash Config Lock-Down */
+    } hsf_status;
+    u16_t regval;
+};
+        
+/**
+ * @brief ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown.
+ * @see http://gitweb.dragonflybsd.org
+ */
+union ich8_hws_flash_ctrl
+{
+    struct ich8_hsflctl
+    {
+        unsigned flcgo      :1;   /**< 0 Flash Cycle Go */
+        unsigned flcycle    :2;   /**< 2:1 Flash Cycle */
+        unsigned reserved   :5;   /**< 7:3 Reserved  */
+        unsigned fldbcount  :2;   /**< 9:8 Flash Data Byte Count */
+        unsigned flockdn    :6;   /**< 15:10 Reserved */
+    } hsf_ctrl;
+    u16_t regval;
+};
+                
+/**
+ * @brief ICH Flash Region Access Permissions.
+ * @see http://gitweb.dragonflybsd.org
+ */
+union ich8_hws_flash_regacc
+{
+    struct ich8_flracc
+    {
+        unsigned grra      :8; /**< 0:7 GbE region Read Access */
+        unsigned grwa      :8; /**< 8:15 GbE region Write Access */
+        unsigned gmrag     :8; /**< 23:16 GbE Master Read Access Grant */
+        unsigned gmwag     :8; /**< 31:24 GbE Master Write Access Grant */
+    } hsf_flregacc;
+    u16_t regval;
+};
+
+/**
+ * @}
+ */
+
+/**
+ * @name Receive Status Field Bits.
+ * @{
+ */
+
+/** Passed In-exact Filter. */
+#define E1000_RX_STATUS_PIF    (1 << 7) 
+/** End of Packet. */
+#define E1000_RX_STATUS_EOP    (1 << 1)
+
+/** Descriptor Done. */
+#define E1000_RX_STATUS_DONE   (1 << 0)
+
+/**
+ * @}
+ */
+
+/**
+ * @name Receive Errors Field Bits.
+ * @{
+ */
+
+/** RX Data Error. */
+#define E1000_RX_ERROR_RXE     (1 << 7)
+
+/** Carrier Extension Error. */
+#define E1000_RX_ERROR_CXE     (1 << 4)
+
+/** Sequence/Framing Error. */
+#define E1000_RX_ERROR_SEQ     (1 << 2)
+
+/** CRC/Alignment Error. */
+#define E1000_RX_ERROR_CE      (1 << 0)
+
+/**
+ * @}
+ */
+
+/**
+ * @name Transmit Command Field Bits.
+ * @{
+ */
+
+/** End of Packet. */
+#define E1000_TX_CMD_EOP       (1 << 0)
+
+/** Insert FCS/CRC. */
+#define E1000_TX_CMD_FCS       (1 << 1)
+
+/** Report Status. */
+#define E1000_TX_CMD_RS                (1 << 3)
+
+/**
+ * @}
+ */
+
+#endif /* __E1000_HW_H */
diff --git a/drivers/e1000/e1000_pci.h b/drivers/e1000/e1000_pci.h
new file mode 100644 (file)
index 0000000..0528aaa
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * @file e1000_pci.h
+ *
+ * @brief PCI Device Identity numbers of Intel Pro/1000
+ *        Gigabit Ethernet cards.
+ *
+ * Parts of this code is based on the DragonflyBSD (FreeBSD)
+ * implementation, and the fxp driver for Minix 3.
+ *
+ * @see http://svn.freebsd.org/viewvc/base/head/sys/dev/e1000/
+ * @see fxp.c
+ *
+ * @author Niek Linnenbank <nieklinnenbank@gmail.com>
+ * @date September 2009
+ *
+ */
+
+#ifndef __E1000_PCI_H
+#define __E1000_PCI_H
+
+/**
+ * @name PCI Device ID's.
+ * @{
+ */
+
+#define E1000_DEV_ID_82542                    0x1000
+#define E1000_DEV_ID_82543GC_FIBER            0x1001
+#define E1000_DEV_ID_82543GC_COPPER           0x1004
+#define E1000_DEV_ID_82544EI_COPPER           0x1008
+#define E1000_DEV_ID_82544EI_FIBER            0x1009
+#define E1000_DEV_ID_82544GC_COPPER           0x100C
+#define E1000_DEV_ID_82544GC_LOM              0x100D
+#define E1000_DEV_ID_82540EM                  0x100E
+#define E1000_DEV_ID_82540EM_LOM              0x1015
+#define E1000_DEV_ID_82540EP_LOM              0x1016
+#define E1000_DEV_ID_82540EP                  0x1017
+#define E1000_DEV_ID_82540EP_LP               0x101E
+#define E1000_DEV_ID_82545EM_COPPER           0x100F
+#define E1000_DEV_ID_82545EM_FIBER            0x1011
+#define E1000_DEV_ID_82545GM_COPPER           0x1026
+#define E1000_DEV_ID_82545GM_FIBER            0x1027
+#define E1000_DEV_ID_82545GM_SERDES           0x1028
+#define E1000_DEV_ID_82546EB_COPPER           0x1010
+#define E1000_DEV_ID_82546EB_FIBER            0x1012
+#define E1000_DEV_ID_82546EB_QUAD_COPPER      0x101D
+#define E1000_DEV_ID_82546GB_COPPER           0x1079
+#define E1000_DEV_ID_82546GB_FIBER            0x107A
+#define E1000_DEV_ID_82546GB_SERDES           0x107B
+#define E1000_DEV_ID_82546GB_PCIE             0x108A
+#define E1000_DEV_ID_82546GB_QUAD_COPPER      0x1099
+#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5
+#define E1000_DEV_ID_82541EI                  0x1013
+#define E1000_DEV_ID_82541EI_MOBILE           0x1018
+#define E1000_DEV_ID_82541ER_LOM              0x1014
+#define E1000_DEV_ID_82541ER                  0x1078
+#define E1000_DEV_ID_82541GI                  0x1076
+#define E1000_DEV_ID_82541GI_LF               0x107C
+#define E1000_DEV_ID_82541GI_MOBILE           0x1077
+#define E1000_DEV_ID_82547EI                  0x1019
+#define E1000_DEV_ID_82547EI_MOBILE           0x101A
+#define E1000_DEV_ID_82547GI                  0x1075
+#define E1000_DEV_ID_82571EB_COPPER           0x105E
+#define E1000_DEV_ID_82571EB_FIBER            0x105F
+#define E1000_DEV_ID_82571EB_SERDES           0x1060
+#define E1000_DEV_ID_82571EB_SERDES_DUAL      0x10D9
+#define E1000_DEV_ID_82571EB_SERDES_QUAD      0x10DA
+#define E1000_DEV_ID_82571EB_QUAD_COPPER      0x10A4
+#define E1000_DEV_ID_82571PT_QUAD_COPPER      0x10D5
+#define E1000_DEV_ID_82571EB_QUAD_FIBER       0x10A5
+#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP   0x10BC
+#define E1000_DEV_ID_82572EI_COPPER           0x107D
+#define E1000_DEV_ID_82572EI_FIBER            0x107E
+#define E1000_DEV_ID_82572EI_SERDES           0x107F
+#define E1000_DEV_ID_82572EI                  0x10B9
+#define E1000_DEV_ID_82573E                   0x108B
+#define E1000_DEV_ID_82573E_IAMT              0x108C
+#define E1000_DEV_ID_82573L                   0x109A
+#define E1000_DEV_ID_82574L                   0x10D3
+#define E1000_DEV_ID_82574LA                  0x10F6
+#define E1000_DEV_ID_82583V                   0x150C
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT   0x1096
+#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT   0x1098
+#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT   0x10BA
+#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT   0x10BB
+#define E1000_DEV_ID_ICH8_IGP_M_AMT           0x1049
+#define E1000_DEV_ID_ICH8_IGP_AMT             0x104A
+#define E1000_DEV_ID_ICH8_IGP_C               0x104B
+#define E1000_DEV_ID_ICH8_IFE                 0x104C
+#define E1000_DEV_ID_ICH8_IFE_GT              0x10C4
+#define E1000_DEV_ID_ICH8_IFE_G               0x10C5
+#define E1000_DEV_ID_ICH8_IGP_M               0x104D
+#define E1000_DEV_ID_ICH9_IGP_M               0x10BF
+#define E1000_DEV_ID_ICH9_IGP_M_AMT           0x10F5
+#define E1000_DEV_ID_ICH9_IGP_M_V             0x10CB
+#define E1000_DEV_ID_ICH9_IGP_AMT             0x10BD
+#define E1000_DEV_ID_ICH9_BM                  0x10E5
+#define E1000_DEV_ID_ICH9_IGP_C               0x294C
+#define E1000_DEV_ID_ICH9_IFE                 0x10C0
+#define E1000_DEV_ID_ICH9_IFE_GT              0x10C3
+#define E1000_DEV_ID_ICH9_IFE_G               0x10C2
+#define E1000_DEV_ID_ICH10_R_BM_LM            0x10CC
+#define E1000_DEV_ID_ICH10_R_BM_LF            0x10CD
+#define E1000_DEV_ID_ICH10_R_BM_V             0x10CE
+#define E1000_DEV_ID_ICH10_D_BM_LM            0x10DE
+#define E1000_DEV_ID_ICH10_D_BM_LF            0x10DF
+#define E1000_DEV_ID_PCH_M_HV_LM              0x10EA
+#define E1000_DEV_ID_PCH_M_HV_LC              0x10EB
+#define E1000_DEV_ID_PCH_D_HV_DM              0x10EF
+#define E1000_DEV_ID_PCH_D_HV_DC              0x10F0
+#define E1000_DEV_ID_82576                    0x10C9
+#define E1000_DEV_ID_82576_FIBER              0x10E6
+#define E1000_DEV_ID_82576_SERDES             0x10E7
+#define E1000_DEV_ID_82576_QUAD_COPPER        0x10E8
+#define E1000_DEV_ID_82576_NS                 0x150A
+#define E1000_DEV_ID_82576_SERDES_QUAD        0x150D
+#define E1000_DEV_ID_82575EB_COPPER           0x10A7
+#define E1000_DEV_ID_82575EB_FIBER_SERDES     0x10A9
+#define E1000_DEV_ID_82575GB_QUAD_COPPER      0x10D6
+#define E1000_DEV_ID_82575GB_QUAD_COPPER_PM   0x10E2
+
+/**
+ * @}
+ */
+
+/**
+ * @name Revision Numbers.
+ * @{
+ */
+
+#define E1000_DEV_RID_82540    0x03
+#define E1000_DEV_RID_82541    0x05
+
+/**
+ * @}
+ */
+
+#endif /* __E1000_PCI_H */
diff --git a/drivers/e1000/e1000_reg.h b/drivers/e1000/e1000_reg.h
new file mode 100644 (file)
index 0000000..bcaefd1
--- /dev/null
@@ -0,0 +1,310 @@
+/**
+ * @file e1000_reg.h
+ *
+ * @brief Hardware specific registers and flags of the Intel
+ *        Pro/1000 Gigabit Ethernet card(s).
+ *
+ * Parts of this code is based on the DragonflyBSD (FreeBSD)
+ * implementation, and the fxp driver for Minix 3.
+ *
+ * @see http://svn.freebsd.org/viewvc/base/head/sys/dev/e1000/
+ * @see fxp.c
+ *
+ * @author Niek Linnenbank <nieklinnenbank@gmail.com>
+ * @date September 2009
+ *
+ */
+
+#ifndef __E1000_REG_H
+#define __E1000_REG_H
+
+/**
+ * @name Controller Registers.
+ * @{
+ */
+
+/** Device Control. */
+#define E1000_REG_CTRL         0x00000
+
+/** Device Status. */
+#define E1000_REG_STATUS       0x00008
+
+/** EEPROM Read. */
+#define E1000_REG_EERD         0x00014
+
+/** Flow Control Address Low. */
+#define E1000_REG_FCAL         0x00028
+
+/** Flow Control Address High. */
+#define E1000_REG_FCAH         0x0002c
+
+/** Flow Control Type. */
+#define E1000_REG_FCT          0x00030
+
+/** Interrupt Cause Read. */
+#define E1000_REG_ICR          0x000c0
+
+/** Interrupt Mask Set/Read Register. */
+#define E1000_REG_IMS          0x000d0
+
+/** Receive Control Register. */
+#define E1000_REG_RCTL         0x00100
+
+/** Transmit Control Register. */
+#define E1000_REG_TCTL         0x00400
+
+/** Flow Control Transmit Timer Value. */
+#define E1000_REG_FCTTV                0x00170
+
+/** Receive Descriptor Base Address Low. */
+#define E1000_REG_RDBAL                0x02800
+
+/** Receive Descriptor Base Address High. */
+#define E1000_REG_RDBAH                0x02804
+
+/** Receive Descriptor Length. */
+#define E1000_REG_RDLEN                0x02808
+
+/** Receive Descriptor Head. */
+#define E1000_REG_RDH          0x02810
+
+/** Receive Descriptor Tail. */
+#define E1000_REG_RDT          0x02818
+
+/** Transmit Descriptor Base Address Low. */
+#define E1000_REG_TDBAL                0x03800
+
+/** Transmit Descriptor Base Address High. */
+#define E1000_REG_TDBAH                0x03804
+
+/** Transmit Descriptor Length. */
+#define E1000_REG_TDLEN                0x03808
+
+/** Transmit Descriptor Head. */
+#define E1000_REG_TDH          0x03810
+
+/** Transmit Descriptor Tail. */
+#define E1000_REG_TDT          0x03818
+
+/** CRC Error Count. */
+#define E1000_REG_CRCERRS      0x04000
+
+/** RX Error Count. */
+#define E1000_REG_RXERRC       0x0400c
+
+/** Missed Packets Count. */
+#define E1000_REG_MPC          0x04010
+
+/** Collision Count. */
+#define E1000_REG_COLC         0x04028
+
+/** Total Packets Received. */
+#define E1000_REG_TPR          0x040D0
+
+/** Total Packets Transmitted. */
+#define E1000_REG_TPT          0x040D4
+
+/** Receive Address Low. */
+#define E1000_REG_RAL          0x05400
+
+/** Receive Address High. */
+#define E1000_REG_RAH          0x05404
+
+/** Multicast Table Array. */
+#define E1000_REG_MTA          0x05200
+
+/**
+ * @}
+ */
+
+/**
+ * @name Control Register Bits.
+ * @{
+ */
+
+/** Auto-Speed Detection Enable. */
+#define E1000_REG_CTRL_ASDE    (1 << 5)
+
+/** Link Reset. */
+#define E1000_REG_CTRL_LRST    (1 << 3)
+
+/** Set Link Up. */
+#define E1000_REG_CTRL_SLU     (1 << 6)
+
+/** Invert Los Of Signal. */
+#define E1000_REG_CTRL_ILOS    (1 << 7)
+
+/** Device Reset. */
+#define E1000_REG_CTRL_RST     (1 << 26)
+
+/** VLAN Mode Enable. */
+#define E1000_REG_CTRL_VME     (1 << 30)
+
+/** PHY Reset. */
+#define E1000_REG_CTRL_PHY_RST (1 << 31)
+
+/**
+ * @}
+ */
+
+/**
+ * @name Status Register Bits.
+ * @{
+ */
+
+/** Link Full Duplex Configuration Indication. */ 
+#define E1000_REG_STATUS_FD     (1 << 0)
+
+/** Link Up Indication. */
+#define E1000_REG_STATUS_LU     (1 << 1)
+
+/** Transmission Paused. */
+#define E1000_REG_STATUS_TXOFF  (1 << 4)
+
+/** Link Speed Setting. */
+#define E1000_REG_STATUS_SPEED ((1 << 6) | (1 << 7))
+
+/**
+ * @}
+ */
+
+/**
+ * @name EEPROM Read Register Bits.
+ * @{
+ */
+
+/** Start Read. */
+#define E1000_REG_EERD_START   (1 << 0)
+
+/** Read Done. */
+#define E1000_REG_EERD_DONE    (1 << 4)
+
+/** Read Address Bit Mask. */
+#define E1000_REG_EERD_ADDR    (0xff   << 8)
+
+/** Read Data Bit Mask. */
+#define E1000_REG_EERD_DATA    (0xffff << 16)
+
+/**
+ * @}
+ */
+
+/**
+ * @name Interrupt Cause Read.
+ * @{
+ */
+
+/** Transmit Descripts Written Back. */
+#define E1000_REG_ICR_TXDW     (1 << 0)
+
+/** Transmit Queue Empty. */
+#define E1000_REG_ICR_TXQE     (1 << 1)
+
+/** Link Status Change. */
+#define E1000_REG_ICR_LSC      (1 << 2)
+
+/** Receiver Overrun. */
+#define E1000_REG_ICR_RXO      (1 << 6)
+
+/** Receiver Timer Interrupt. */
+#define E1000_REG_ICR_RXT      (1 << 7)
+
+/**
+ * @}
+ */
+
+/**
+ * @name Interrupt Mask Set/Read Register Bits.
+ * @{
+ */
+
+/** Transmit Descripts Written Back. */
+#define E1000_REG_IMS_TXDW     (1 << 0)
+
+/** Transmit Queue Empty. */
+#define E1000_REG_IMS_TXQE     (1 << 1)
+
+/** Link Status Change. */
+#define E1000_REG_IMS_LSC      (1 << 2)
+
+/** Receiver FIFO Overrun. */
+#define E1000_REG_IMS_RXO      (1 << 6)
+
+/** Receiver Timer Interrupt. */
+#define E1000_REG_IMS_RXT      (1 << 7)
+
+/**
+ * @}
+ */
+
+/**
+ * @name Receive Control Register Bits.
+ * @{
+ */
+
+/** Receive Enable. */
+#define E1000_REG_RCTL_EN      (1 << 1)
+
+/** Multicast Promiscious Enable. */
+#define E1000_REG_RCTL_MPE     (1 << 4)
+
+/** Broadcast Accept Mode. */
+#define E1000_REG_RCTL_BAM     (1 << 15)
+
+/** Receive Buffer Size. */
+#define E1000_REG_RCTL_BSIZE   ((1 << 16) | (1 << 17))
+
+/**
+ * @}
+ */
+
+/**
+ * @name Transmit Control Register Bits.
+ * @{
+ */
+
+/** Transmit Enable. */
+#define E1000_REG_TCTL_EN      (1 << 1)
+
+/** Pad Short Packets. */
+#define E1000_REG_TCTL_PSP     (1 << 3)
+
+/**
+ * @}
+ */
+
+/**
+ * @name Receive Address High Register Bits.
+ * @{
+ */
+
+/** Receive Address Valid. */
+#define E1000_REG_RAH_AV       (1 << 31)
+
+/**
+ * @}
+ */
+
+/**
+ * @name ICH Flash Registers.
+ * @see http://gitweb.dragonflybsd.org
+ * @{
+ */
+
+#define ICH_FLASH_GFPREG                 0x0000 
+#define ICH_FLASH_HSFSTS                 0x0004 
+#define ICH_FLASH_HSFCTL                 0x0006 
+#define ICH_FLASH_FADDR                  0x0008 
+#define ICH_FLASH_FDATA0                 0x0010 
+#define FLASH_GFPREG_BASE_MASK           0x1FFF 
+#define FLASH_SECTOR_ADDR_SHIFT          12
+#define ICH_FLASH_READ_COMMAND_TIMEOUT   500
+#define ICH_FLASH_LINEAR_ADDR_MASK       0x00FFFFFF
+#define ICH_CYCLE_READ                   0 
+#define ICH_FLASH_CYCLE_REPEAT_COUNT     10 
+
+/**
+ * @}
+ */
+
+#endif /* __E1000_REG_H */
index 3c401bab96596c006b12997aae7af93e67be9be6..a49f16f6f04c8a3bd241d76564438504ce93b744 100644 (file)
@@ -129,10 +129,13 @@ struct pci_device pci_device_table[]=
        { 0x5333, 0x88d0, "S3 Vision 964 vers 0" },
        { 0x5333, 0x8a01, "S3 Virge/DX or /GX" },
        { 0x8086, 0x1004, "Intel 82543GC Gigabit Ethernet Controller" },
+       { 0x8086, 0x100E, "Intel PRO/1000 MT Desktop Adapter" },
        { 0x8086, 0x1029, "Intel EtherExpressPro100 ID1029" },
        { 0x8086, 0x1030, "Intel Corporation 82559 InBusiness 10/100" },
        { 0x8086, 0x103d, "Intel Corporation 82801DB PRO/100 VE (MOB)" },
        { 0x8086, 0x1064, "Intel Corporation 82562 PRO/100 VE" },
+       { 0x8086, 0x107C, "Intel PRO/1000 GT Desktop Adapter" },
+       { 0x8086, 0x10CD, "Intel PRO/1000 Gigabit Network Connection" },
        { 0x8086, 0x1209, "Intel EtherExpressPro100 82559ER" },
        { 0x8086, 0x1229, "Intel EtherExpressPro100 82557/8/9" },
        { 0x8086, 0x122D, "Intel 82437FX" },
index d886cae7b69240378e25b186db7287916db1cc61..e8a2ba0a452ecfdb3cabc6fbf68af4237aac00cb 100644 (file)
@@ -517,3 +517,25 @@ driver filter
                bios_wini
        ;
 };
+
+driver e1000
+{
+       system
+               UMAP            # 14
+               IRQCTL          # 19
+               DEVIO           # 21
+               SETALARM        # 24
+               TIMES           # 25
+               GETINFO         # 26
+               SAFECOPYFROM    # 31
+               SAFECOPYTO      # 32
+               SETGRANT        # 34
+               SYSCTL
+       ;
+       pci device      8086/100e;
+       pci device      8086/107c;
+       pci device      8086/10cd;
+       ipc
+               SYSTEM PM RS LOG TTY DS VM
+               pci inet ;
+};
index 0430f46e59900cf9adf0f4cb31d26518ee97de1a..295fe7ef013a718cada1a7f5bd2819f47a33d199 100644 (file)
@@ -91,7 +91,7 @@ start)
     fi
 
     # start only network drivers that are in use
-    for driver in lance rtl8139 rtl8169 fxp dpeth dp8390 orinoco
+    for driver in lance rtl8139 rtl8169 fxp e1000 dpeth dp8390 orinoco
     do
         if grep " $driver " /etc/inet.conf > /dev/null  2>&1
         then