Patch: adding support for Intel ExpressPro1000 GB Copper

"Natalie Protasevich" <[email protected]> Thu, 4 May 2006 17:46:15 -0600
Newsgroups gmane.network.etherboot.devel
Message-ID <[email protected]>
Hello,
This is an update to e1000 etherboot driver to enable the ExpressPro1000
copper chip.
The update includes receive ring buffer fix done by Eric Biederman to
increase the ring size from 1 to 8 buffers. This was needed to prevent the
hang which was caused by inabiliy of the single buffer ring to handle
multicast traffic.

Thanks,
--Natalie
eth-e1000-80003es2lan.diff (text/plain, 18.5 KB)
diff -Naurp etherboot-5.4.2/src/drivers/net/e1000.c etherboot-5.4.2-nbp/src/drivers/net/e1000.c
--- etherboot-5.4.2/src/drivers/net/e1000.c	2006-05-02 18:09:56.638636198 -0600
+++ etherboot-5.4.2-nbp/src/drivers/net/e1000.c	2006-05-02 18:09:32.584824473 -0600
@@ -215,6 +218,11 @@ e1000_set_phy_type(struct e1000_hw *hw)
 	case IGP01E1000_I_PHY_ID:
 		hw->phy_type = e1000_phy_igp;
 		break;
+	case GG82563_E_PHY_ID:
+		if (hw->mac_type == e1000_80003es2lan) {
+			hw->phy_type = e1000_phy_gg82563;
+			break;
+		}
 	default:
 		/* Should never have loaded on this device */
 		hw->phy_type = e1000_phy_undefined;
@@ -379,6 +387,9 @@ e1000_set_mac_type(struct e1000_hw *hw)
 	case E1000_DEV_ID_82547GI:
 		hw->mac_type = e1000_82547_rev_2;
 		break;
+	case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
+		hw->mac_type = e1000_80003es2lan;
+		break;
 	default:
 		/* Should never have loaded on this device */
 		return -E1000_ERR_MAC_TYPE;
@@ -640,6 +651,21 @@ e1000_init_hw(struct e1000_hw *hw)
 		case e1000_82545_rev_3:
 		case e1000_82546_rev_3:
 			break;
+		case e1000_80003es2lan:
+		{
+			int32_t timeout = 200;
+			while(timeout) {
+				if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) 
+					break;
+				else mdelay(10);
+				timeout--;
+			}
+			if(!timeout) {
+				/* We don't want to continue accessing MAC registers. */
+				return -E1000_ERR_RESET;
+			}
+			break;
+		}
 		default:
 			if (hw->mac_type >= e1000_82543) {
 				/* See e1000_get_bus_info() of the Linux driver */
@@ -1001,6 +1027,159 @@ e1000_setup_fiber_serdes_link(struct e10
 	return E1000_SUCCESS;
 }
 
+int32_t
+e1000_read_kmrn_reg(struct e1000_hw *hw,
+			uint32_t reg_addr,
+			uint16_t *data)
+{
+	uint32_t reg_val;
+	DEBUGFUNC("e1000_read_kmrn_reg");
+	
+	/* Write register address */
+	reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
+			E1000_KUMCTRLSTA_OFFSET) |
+			E1000_KUMCTRLSTA_REN;
+	E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+	udelay(2);
+
+	/* Read the data returned */
+	reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+	*data = (uint16_t)reg_val;
+
+	return E1000_SUCCESS;
+}
+
+int32_t
+e1000_write_kmrn_reg(struct e1000_hw *hw,
+			uint32_t reg_addr,
+			uint16_t data)
+{
+	uint32_t reg_val;
+	DEBUGFUNC("e1000_write_kmrn_reg");
+
+	reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
+			E1000_KUMCTRLSTA_OFFSET) | data;
+	E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+	udelay(2);
+
+	return E1000_SUCCESS;
+}
+
+/********************************************************************
+* Copper link setup for e1000_phy_gg82563 series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+
+static int32_t
+e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+{
+	int32_t ret_val;
+	uint16_t phy_data;
+	uint32_t reg_data;
+
+	DEBUGFUNC("e1000_copper_link_ggp_setup\n");
+
+	/* Enable CRS on TX for half-duplex operation. */
+	ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+	                             &phy_data);
+	if(ret_val)
+		return ret_val;
+
+	phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+	/* Use 25MHz for both link down and 1000BASE-T for Tx clock */
+	phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ;
+
+	ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+                                      phy_data);
+	if(ret_val)
+		return ret_val;
+	/* Options:
+	 *   MDI/MDI-X = 0 (default)
+	 *   0 - Auto for all speeds
+	 *   1 - MDI mode
+	 *   2 - MDI-X mode
+	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+	 */
+	ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data);
+	if(ret_val)
+		return ret_val;
+
+	phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
+
+	phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
+
+	/* Options:
+	 *   disable_polarity_correction = 0 (default)
+	 *       Automatic Correction for Reversed Cable Polarity
+	 *   0 - Disabled
+	 *   1 - Enabled
+	 */
+	phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
+	ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
+
+	if(ret_val)
+		return ret_val;
+
+	/* SW Reset the PHY so all changes take effect */
+	ret_val = e1000_phy_reset(hw);
+	if (ret_val) {
+	    DEBUGOUT("Error Resetting the PHY\n");
+	    return ret_val;
+	}
+
+	if (hw->mac_type == e1000_80003es2lan) {
+		/* Bypass RX and TX FIFO's */
+		ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL,
+	        				E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS |
+	        				E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS);
+		if (ret_val)
+       		 	return ret_val;
+
+		ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &phy_data);
+		if (ret_val)
+			ret_val;
+
+		phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
+		ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, phy_data);
+
+		if (ret_val)
+			return ret_val;
+
+		reg_data = E1000_READ_REG(hw, CTRL_EXT);
+		reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
+		E1000_WRITE_REG(hw, CTRL_EXT, reg_data);
+	
+		ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+        						&phy_data);
+		if (ret_val)
+			return ret_val;
+
+		/* Enable Electrical Idle on the PHY */
+		phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
+		ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+							phy_data);
+	
+		if (ret_val)
+			return ret_val;
+
+		ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+        						&phy_data);
+		if (ret_val)
+			return ret_val;
+
+		/* Disable Pass False Carrier on the PHY */
+		phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+
+		ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+            						phy_data);
+		if (ret_val)
+			return ret_val;
+	}
+
+	return E1000_SUCCESS;
+}
+
 /******************************************************************************
 * Detects which PHY is present and the speed and duplex
 *
@@ -1017,6 +1196,33 @@ e1000_setup_copper_link(struct e1000_hw 
 	DEBUGFUNC("e1000_setup_copper_link");
 	
 	ctrl = E1000_READ_REG(hw, CTRL);
+
+	if(hw->mac_type == e1000_80003es2lan) {
+		uint16_t reg_data;
+		/* Set the mac to wait the maximum time between each
+		 * iteration and increase the max iterations when
+		 * polling the phy; this fixes erroneous timeouts at 10Mbps. */
+		ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+		if (ret_val)
+			return ret_val;
+		ret_val = e1000_read_kmrn_reg(hw, GG82563_REG(0x34, 9), &reg_data);
+		if (ret_val)
+			return ret_val;
+		reg_data |= 0x3F;
+		ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
+		if (ret_val)
+			return ret_val;
+		ret_val = e1000_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
+									&reg_data);
+		if (ret_val)
+			return ret_val;
+		reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING;
+		ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
+									reg_data);
+		if (ret_val)
+			return ret_val;
+	}
+
 	/* With 82543, we need to force speed and duplex on the MAC equal to what
 	 * the PHY speed and duplex configuration is. In addition, we need to
 	 * perform a hardware reset on the PHY to take it out of reset.
@@ -1038,6 +1244,12 @@ e1000_setup_copper_link(struct e1000_hw 
 	}
 	DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
 
+	if (hw->phy_type == e1000_phy_gg82563) {
+		ret_val = e1000_copper_link_ggp_setup(hw);
+		if(ret_val)
+			return ret_val;
+	}
+
 	if(hw->mac_type <= e1000_82543 ||
 	   hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
 #if 0
@@ -1046,9 +1258,10 @@ e1000_setup_copper_link(struct e1000_hw 
 
 	if(!hw->phy_reset_disable) {
 #else
-	   hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
+	   hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2 || 
+						hw->mac_type == e1000_80003es2lan) {
 #endif
-	if (hw->phy_type == e1000_phy_igp) {
+	if (hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_gg82563) {
 
 		if((ret_val = e1000_phy_reset(hw))) {
 			DEBUGOUT("Error Resetting the PHY\n");
@@ -2553,6 +2766,15 @@ e1000_detect_gig_phy(struct e1000_hw *hw
 
 	DEBUGFUNC("e1000_detect_gig_phy");
 	
+	/* ESB-2 PHY reads require e1000_phy_gg82563 to be set because of a work-
+	 * around that forces PHY page 0 to be set or the reads fail.  The rest of
+	 * the code in this routine uses e1000_read_phy_reg to read the PHY ID.
+	 * So for ESB-2 we need to have this set so our reads won't fail.  If the
+	 * attached PHY is not a e1000_phy_gg82563, the routines below will figure
+	 * this out as well. */
+	if (hw->mac_type == e1000_80003es2lan)
+		hw->phy_type = e1000_phy_gg82563;
+	
 	/* Read the PHY ID Registers to identify which PHY is onboard. */
 	if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high)))
 		return ret_val;
@@ -2587,6 +2809,9 @@ e1000_detect_gig_phy(struct e1000_hw *hw
 	case e1000_82547_rev_2:
 		if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
 		break;
+	case e1000_80003es2lan:
+		if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
+		break;
 	default:
 		DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
 		return -E1000_ERR_CONFIG;
@@ -3273,6 +3498,8 @@ e1000_reset(struct e1000_hw *hw)
 
 	if(hw->mac_type < e1000_82547) {
 		pba = E1000_PBA_48K;
+	} else if (hw->mac_type == e1000_80003es2lan) {
+		pba = E1000_PBA_38K;
 	} else {
 		pba = E1000_PBA_30K;
 	}
@@ -3733,6 +3963,7 @@ PCI_ROM(0x8086, 0x1079, "e1000-82546gb-c
 PCI_ROM(0x8086, 0x107a, "e1000-82546gb-fiber",	     "Intel EtherExpressPro1000 82546GB Fiber"),
 PCI_ROM(0x8086, 0x107b, "e1000-82546gb-serdes",	     "Intel EtherExpressPro1000 82546GB SERDES"),
 PCI_ROM(0x8086, 0x107c, "e1000-82541pi",	     "Intel EtherExpressPro1000 82541PI"),
+PCI_ROM(0x8086, 0x1096, "e1000_80003es2lan",	     "Intel EtherExpressPro1000 GB COPPER"),
 };
 
 static struct pci_driver e1000_driver __pci_driver = {
diff -Naurp etherboot-5.4.2/src/drivers/net/e1000_hw.h etherboot-5.4.2-nbp/src/drivers/net/e1000_hw.h
--- etherboot-5.4.2/src/drivers/net/e1000_hw.h	2006-05-02 18:10:06.272958651 -0600
+++ etherboot-5.4.2-nbp/src/drivers/net/e1000_hw.h	2006-05-02 18:09:32.585824299 -0600
@@ -54,6 +54,7 @@ typedef enum {
     e1000_82541_rev_2,
     e1000_82547,
     e1000_82547_rev_2,
+    e1000_80003es2lan,
     e1000_num_macs
 } e1000_mac_type;
 
@@ -187,6 +188,7 @@ typedef enum {
 typedef enum {
     e1000_phy_m88 = 0,
     e1000_phy_igp,
+    e1000_phy_gg82563,
     e1000_phy_undefined = 0xFF
 } e1000_phy_type;
 
@@ -247,6 +249,7 @@ struct e1000_eeprom_info {
 #define E1000_ERR_PHY_TYPE 6
 #define E1000_ERR_NOLINK   7
 #define E1000_ERR_TIMEOUT  8
+#define E1000_ERR_RESET    9
 
 #define E1000_READ_REG_IO(a, reg) \
 	e1000_read_reg_io((a), E1000_##reg)
@@ -284,6 +287,7 @@ struct e1000_eeprom_info {
 #define E1000_DEV_ID_82546GB_FIBER       0x107A
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82547EI             0x1019
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT     0x1096
 
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -689,6 +693,7 @@ struct e1000_ffvt_entry {
 #define E1000_FFLT     0x05F00  /* Flexible Filter Length Table - RW Array */
 #define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
 #define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
+#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */
 
 /* Register Set (82542)
  *
@@ -823,6 +828,7 @@ struct e1000_ffvt_entry {
 #define E1000_82542_TDFT     0x08018
 #define E1000_82542_FFMT     E1000_FFMT
 #define E1000_82542_FFVT     E1000_FFVT
+#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA
 
 /* Statistics counters collected by the MAC */
 struct e1000_hw_stats {
@@ -1059,6 +1065,7 @@ struct e1000_hw {
 #ifndef E1000_EEPROM_GRANT_ATTEMPTS
 #define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
 #endif
+#define E1000_EECD_AUTO_RD   0x00000200  /* EEPROM Auto Read done */
 
 /* EEPROM Read */
 #define E1000_EERD_START      0x00000001 /* Start Read */
@@ -1284,6 +1291,7 @@ struct e1000_hw {
 #define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
 #define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
 #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.still to be processed. */
 
 /* Transmit Configuration Word */
 #define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
@@ -1374,7 +1382,7 @@ struct e1000_hw {
 #define E1000_MANC_IPV6_EN       0x00000800 /* Enable IPv6 */
 #define E1000_MANC_SNAP_EN       0x00001000 /* Accept LLC/SNAP */
 #define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
-#define E1000_MANC_NEIGHBOR_EN   0x00004000 /* Enable Neighbor Discovery 
+#define E1000_MANC_NEIGHBOR_EN   0x00004000 /* Enable Neighbor Discovery
                                              * Filtering */
 #define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
 #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
@@ -1394,6 +1402,32 @@ struct e1000_hw {
 
 #define E1000_MDALIGN          4096
 
+#define E1000_KUMCTRLSTA_MASK           0x0000FFFF
+#define E1000_KUMCTRLSTA_OFFSET         0x001F0000
+#define E1000_KUMCTRLSTA_OFFSET_SHIFT   16
+#define E1000_KUMCTRLSTA_REN            0x00200000
+
+#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL      0x00000000
+#define E1000_KUMCTRLSTA_OFFSET_CTRL           0x00000001
+#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL       0x00000002
+#define E1000_KUMCTRLSTA_OFFSET_DIAG           0x00000003
+#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS       0x00000004
+#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM      0x00000009
+#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL        0x00000010
+#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES     0x0000001E
+#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES      0x0000001F
+
+/* FIFO Control */
+#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS   0x00000008
+#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS   0x00000800
+
+/* In-Band Control */
+#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING  0x00000010
+
+/* Half-Duplex Control */
+#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
+#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT  0x00000000
+
 /* EEPROM Commands - Microwire */
 #define EEPROM_READ_OPCODE_MICROWIRE  0x6  /* EEPROM read opcode */
 #define EEPROM_WRITE_OPCODE_MICROWIRE 0x5  /* EEPROM write opcode */
@@ -1533,6 +1567,7 @@ struct e1000_hw {
 #define E1000_PBA_22K 0x0016
 #define E1000_PBA_24K 0x0018
 #define E1000_PBA_30K 0x001E
+#define E1000_PBA_38K 0x0026
 #define E1000_PBA_40K 0x0028
 #define E1000_PBA_48K 0x0030    /* 48KB, default RX allocation */
 
@@ -2019,6 +2054,43 @@ struct e1000_hw {
 #define IGP01E1000_ANALOG_FUSE_FINE_1               0x0080
 #define IGP01E1000_ANALOG_FUSE_FINE_10              0x0500
 
+
+/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
+#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE  0x0002 /* 1=Polarity Reversal Disabled */
+#define GG82563_PSCR_POWER_DOWN                 0x0004 /* 1=Power Down */
+#define GG82563_PSCR_COPPER_TRANSMITER_DISABLE  0x0008 /* 1=Transmitter Disabled */
+#define GG82563_PSCR_CROSSOVER_MODE_MASK        0x0060
+#define GG82563_PSCR_CROSSOVER_MODE_MDI         0x0000 /* 00=Manual MDI configuration */
+#define GG82563_PSCR_CROSSOVER_MODE_MDIX        0x0020 /* 01=Manual MDIX configuration */
+#define GG82563_PSCR_CROSSOVER_MODE_AUTO        0x0060 /* 11=Automatic crossover */
+
+/* PHY Specific Control Register 2 (Page 0, Register 26) */
+#define GG82563_PSCR2_REVERSE_AUTO_NEG              0x2000 /* 1=Reverse Auto-Negotiation */
+#define GG82563_PSCR2_TRANSMITER_TYPE_MASK          0x8000
+#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_B      0x0000 /* 0=Class B */
+#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_A      0x8000 /* 1=Class A */
+
+/* MAC Specific Control Register (Page 2, Register 21) */
+/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
+#define GG82563_MSCR_TX_CLK_MASK                    0x0007
+#define GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ           0x0004
+#define GG82563_MSCR_TX_CLK_100MBPS_25MHZ           0x0005
+#define GG82563_MSCR_TX_CLK_1000MBPS_2_5MHZ         0x0006
+#define GG82563_MSCR_TX_CLK_1000MBPS_25MHZ          0x0007
+#define GG82563_MSCR_ASSERT_CRS_ON_TX               0x0010 /* 1=Assert */
+
+/* Kumeran Mode Control Register (Page 193, Register 16) */
+#define GG82563_KMCR_PHY_LEDS_EN                    0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */
+#define GG82563_KMCR_FORCE_LINK_UP                  0x0040 /* 1=Force Link Up */
+#define GG82563_KMCR_PASS_FALSE_CARRIER             0x0800
+
+/* Power Management Control Register (Page 193, Register 20) */
+#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE         0x0001 /* 1=Enalbe SERDES Electrical Idle */
+#define GG82563_PMCR_FORCE_POWER_STATE              0x0080 /* 1=Force Power State */
+
+/* In-Band Control Register (Page 194, Register 18) */
+#define GG82563_ICR_DIS_PADDING                     0x0010 /* Disable Padding Use */
+
 /* Bit definitions for valid PHY IDs. */
 #define M88E1000_E_PHY_ID  0x01410C50
 #define M88E1000_I_PHY_ID  0x01410C30
@@ -2027,6 +2099,7 @@ struct e1000_hw {
 #define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
 #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
 #define M88E1011_I_REV_4   0x04
+#define GG82563_E_PHY_ID   0x01410CA0
 
 /* Miscellaneous PHY bit definitions. */
 #define PHY_PREAMBLE        0xFFFFFFFF
@@ -2055,4 +2128,35 @@ struct e1000_hw {
 #define AUTONEG_ADVERTISE_10_100_ALL    0x000F	/* All 10/100 speeds*/
 #define AUTONEG_ADVERTISE_10_ALL        0x0003	/* 10Mbps Full & Half speeds*/
 
+#define GG82563_PAGE_SHIFT        5
+#define GG82563_REG(page, reg)    \
+        (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+#define GG82563_MIN_ALT_REG       30
+
+/* GG82563 Specific Registers */
+#define GG82563_PHY_SPEC_CTRL           \
+        GG82563_REG(0, 16) /* PHY Specific Control */
+#define GG82563_PHY_SPEC_STATUS_2       \
+        GG82563_REG(0, 19) /* PHY Specific Status 2 */
+#define GG82563_PHY_SPEC_CTRL_2         \
+        GG82563_REG(0, 26) /* PHY Specific Control 2 */
+#define GG82563_PHY_MAC_SPEC_CTRL       \
+        GG82563_REG(2, 21) /* MAC Specific Control Register */
+#define GG82563_PHY_MAC_SPEC_CTRL_2     \
+        GG82563_REG(2, 26) /* MAC Specific Control 2 */
+
+/* Page 193 - Port Control Registers */
+#define GG82563_PHY_KMRN_MODE_CTRL   \
+        GG82563_REG(193, 16) /* Kumeran Mode Control */
+#define GG82563_PHY_DEVICE_ID           \
+        GG82563_REG(193, 19) /* Device ID */
+#define GG82563_PHY_PWR_MGMT_CTRL       \
+        GG82563_REG(193, 20) /* Power Management Control */
+
+/* Page 194 - KMRN Registers */
+#define GG82563_PHY_KMRN_CTRL           \
+        GG82563_REG(194, 17) /* Control */
+#define GG82563_PHY_INBAND_CTRL         \
+        GG82563_REG(194, 18) /* Inband Control */
+
 #endif /* _E1000_HW_H_ */
eth-e1000-ring-buf-fix.diff (text/plain, 2 KB)
diff -Naurp etherboot-5.4.2/src/drivers/net/e1000.c etherboot-5.4.2-nbp/src/drivers/net/e1000.c
--- etherboot-5.4.2/src/drivers/net/e1000.c	2006-05-02 18:09:56.638636198 -0600
+++ etherboot-5.4.2-nbp/src/drivers/net/e1000.c	2006-05-02 18:09:32.584824473 -0600
@@ -87,11 +87,14 @@ typedef enum {
 
 #include "e1000_hw.h"
 
+#define RX_BUFS 	8
+#define MAX_PACKET 	2096
+
 /* NIC specific static variables go here */
 static struct e1000_hw hw;
 static char tx_pool[128 + 16];
 static char rx_pool[128 + 16];
-static char packet[2096];
+static char packets[MAX_PACKET * RX_BUFS];
 
 static struct e1000_tx_desc *tx_base;
 static struct e1000_rx_desc *rx_base;
@@ -3386,11 +3613,10 @@ e1000_io_write(struct e1000_hw *hw __unu
 static void fill_rx (void)
 {
 	struct e1000_rx_desc *rd;
-	rx_last = rx_tail;
 	rd = rx_base + rx_tail;
-	rx_tail = (rx_tail + 1) % 8;
 	memset (rd, 0, 16);
-	rd->buffer_addr = virt_to_bus(&packet);
+	rd->buffer_addr = virt_to_bus(&packets[MAX_PACKET*(rx_tail%RX_BUFS)]);
+	rx_tail = (rx_tail + 1) % 8;
 	E1000_WRITE_REG (&hw, RDT, rx_tail);
 }
 
@@ -3398,6 +3624,7 @@ static void init_descriptor (void)
 {
 	unsigned long ptr;
 	unsigned long tctl;
+	int i;
 
 	ptr = virt_to_phys(tx_pool);
 	if (ptr & 0xf)
@@ -3458,7 +3685,8 @@ static void init_descriptor (void)
 		E1000_RCTL_BAM | 
 		E1000_RCTL_SZ_2048 | 
 		E1000_RCTL_MPE);
-	fill_rx();
+	for (i = 0; i < RX_BUFS; i++)
+		fill_rx();
 }
 
 
@@ -3473,6 +3701,7 @@ e1000_poll (struct nic *nic, int retriev
 	/* nic->packet should contain data on return */
 	/* nic->packetlen should contain length of data */
 	struct e1000_rx_desc *rd;
+	char *packet = &packets[MAX_PACKET*(rx_last%RX_BUFS)];
 	uint32_t icr;
 
 	rd = rx_base + rx_last;
@@ -3484,6 +3713,7 @@ e1000_poll (struct nic *nic, int retriev
 	//      printf("recv: packet %! -> %! len=%d \n", packet+6, packet,rd->Length);
 	memcpy (nic->packet, packet, rd->length);
 	nic->packetlen = rd->length;
+	rx_last = (rx_last + 1) %8;
 	fill_rx ();
 
 	/* Acknowledge interrupt. */