1 /* 2 * This file is provided under a CDDLv1 license. When using or 3 * redistributing this file, you may do so under this license. 4 * In redistributing this file this license must be included 5 * and no other modification of this header file is permitted. 6 * 7 * CDDL LICENSE SUMMARY 8 * 9 * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved. 10 * 11 * The contents of this file are subject to the terms of Version 12 * 1.0 of the Common Development and Distribution License (the "License"). 13 * 14 * You should have received a copy of the License with this software. 15 * You can obtain a copy of the License at 16 * http://www.opensolaris.org/os/licensing. 17 * See the License for the specific language governing permissions 18 * and limitations under the License. 19 */ 20 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms of the CDDLv1. 24 */ 25 #include "e1000_api.h" 26 27 #define E1000_FIFO_MULTIPLIER 0x80 28 #define E1000_FIFO_HDR_SIZE 0x10 29 #define E1000_FIFO_GRANULARITY 0x10 30 #define E1000_FIFO_PAD_82547 0x3E0 31 #define E1000_ERR_FIFO_WRAP 8 32 33 #define DSP_RESET_ENABLE 0x0 34 #define DSP_RESET_DISABLE 0x2 35 #define E1000_MAX_DSP_RESETS 10 36 37 #define E1000_ROUNDUP(size, unit) (((size) + (unit) - 1) & ~((unit) - 1)) 38 39 40 /* 41 * e1000_ttl_workaround_enabled_82541 - Returns current TTL workaround status 42 * @hw: pointer to the HW structure 43 * 44 * Returns the current status of the TTL workaround, as to whether the 45 * workaround is enabled or disabled. 46 */ 47 bool 48 e1000_ttl_workaround_enabled_82541(struct e1000_hw *hw) 49 { 50 struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 51 bool state = false; 52 53 DEBUGFUNC("e1000_ttl_workaround_enabled_82541"); 54 55 if ((hw->mac.type != e1000_82541) && (hw->mac.type != e1000_82547)) 56 goto out; 57 58 state = dev_spec->ttl_workaround; 59 60 out: 61 return (state); 62 } 63 64 /* 65 * e1000_fifo_workaround_82547 - Workaround for Tx fifo failure 66 * @hw: pointer to the HW structure 67 * @length: length of next outgoing frame 68 * 69 * Returns: E1000_ERR_FIFO_WRAP if the next packet cannot be transmitted yet 70 * E1000_SUCCESS if the next packet can be transmitted 71 * 72 * Workaround for the 82547 Tx fifo failure. 73 */ 74 s32 75 e1000_fifo_workaround_82547(struct e1000_hw *hw, u16 length) 76 { 77 struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 78 u32 tctl; 79 s32 ret_val = E1000_SUCCESS; 80 u16 fifo_pkt_len; 81 82 DEBUGFUNC("e1000_fifo_workaround_82547"); 83 84 if (hw->mac.type != e1000_82547) 85 goto out; 86 87 /* 88 * Get the length as seen by the FIFO of the next real 89 * packet to be transmitted. 90 */ 91 fifo_pkt_len = E1000_ROUNDUP(length + E1000_FIFO_HDR_SIZE, 92 E1000_FIFO_GRANULARITY); 93 94 if (fifo_pkt_len <= (E1000_FIFO_PAD_82547 + E1000_FIFO_HDR_SIZE)) 95 goto out; 96 97 if ((dev_spec->tx_fifo_head + fifo_pkt_len) < 98 (dev_spec->tx_fifo_size + E1000_FIFO_PAD_82547)) 99 goto out; 100 101 if (E1000_READ_REG(hw, E1000_TDT(0)) != 102 E1000_READ_REG(hw, E1000_TDH(0))) { 103 ret_val = -E1000_ERR_FIFO_WRAP; 104 goto out; 105 } 106 107 if (E1000_READ_REG(hw, E1000_TDFT) != E1000_READ_REG(hw, E1000_TDFH)) { 108 ret_val = -E1000_ERR_FIFO_WRAP; 109 goto out; 110 } 111 112 if (E1000_READ_REG(hw, E1000_TDFTS) != 113 E1000_READ_REG(hw, E1000_TDFHS)) { 114 ret_val = -E1000_ERR_FIFO_WRAP; 115 goto out; 116 } 117 118 /* Disable the tx unit to avoid further pointer movement */ 119 tctl = E1000_READ_REG(hw, E1000_TCTL); 120 E1000_WRITE_REG(hw, E1000_TCTL, tctl & ~E1000_TCTL_EN); 121 122 /* Reset the fifo pointers. */ 123 E1000_WRITE_REG(hw, E1000_TDFT, dev_spec->tx_fifo_start); 124 E1000_WRITE_REG(hw, E1000_TDFH, dev_spec->tx_fifo_start); 125 E1000_WRITE_REG(hw, E1000_TDFTS, dev_spec->tx_fifo_start); 126 E1000_WRITE_REG(hw, E1000_TDFHS, dev_spec->tx_fifo_start); 127 128 /* Re-enabling tx unit */ 129 E1000_WRITE_REG(hw, E1000_TCTL, tctl); 130 E1000_WRITE_FLUSH(hw); 131 132 dev_spec->tx_fifo_head = 0; 133 134 out: 135 return (ret_val); 136 } 137 138 /* 139 * e1000_update_tx_fifo_head - Update Tx fifo head pointer 140 * @hw: pointer to the HW structure 141 * @length: length of next outgoing frame 142 * 143 * Updates the SW calculated Tx FIFO head pointer. 144 */ 145 void 146 e1000_update_tx_fifo_head_82547(struct e1000_hw *hw, u32 length) 147 { 148 struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 149 150 DEBUGFUNC("e1000_update_tx_fifo_head_82547"); 151 152 if (hw->mac.type != e1000_82547) 153 return; 154 155 dev_spec->tx_fifo_head += E1000_ROUNDUP(length + E1000_FIFO_HDR_SIZE, 156 E1000_FIFO_GRANULARITY); 157 158 if (dev_spec->tx_fifo_head > dev_spec->tx_fifo_size) 159 dev_spec->tx_fifo_head -= dev_spec->tx_fifo_size; 160 } 161 162 /* 163 * e1000_set_ttl_workaround_state_82541 - Enable/Disables TTL workaround 164 * @hw: pointer to the HW structure 165 * @state: boolean to enable/disable TTL workaround 166 * 167 * For 82541 or 82547 only silicon, allows the driver to enable/disable the 168 * TTL workaround. 169 */ 170 void 171 e1000_set_ttl_workaround_state_82541(struct e1000_hw *hw, bool state) 172 { 173 struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 174 175 DEBUGFUNC("e1000_set_ttl_workaround_state_82541"); 176 177 if ((hw->mac.type != e1000_82541) && (hw->mac.type != e1000_82547)) 178 return; 179 180 dev_spec->ttl_workaround = state; 181 } 182 183 /* 184 * e1000_igp_ttl_workaround_82547 - Workaround for long TTL on 100HD hubs 185 * @hw: pointer to the HW structure 186 * 187 * Returns: E1000_ERR_PHY if fail to read/write the PHY 188 * E1000_SUCCESS in any other case 189 * 190 * This function, specific to 82547 hardware only, needs to be called every 191 * second. It checks if a parallel detect fault has occurred. If a fault 192 * occurred, disable/enable the DSP reset mechanism up to 5 times (once per 193 * second). If link is established, stop the workaround and ensure the DSP 194 * reset is enabled. 195 */ 196 s32 197 e1000_igp_ttl_workaround_82547(struct e1000_hw *hw) 198 { 199 struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541; 200 s32 ret_val = E1000_SUCCESS; 201 u16 phy_data = 0; 202 u16 dsp_value = DSP_RESET_ENABLE; 203 bool link; 204 205 DEBUGFUNC("e1000_igp_ttl_workaround_82547"); 206 207 /* The workaround needed only for B-0 silicon HW */ 208 if ((hw->mac.type != e1000_82541) && (hw->mac.type != e1000_82547)) 209 goto out; 210 211 if (!(e1000_ttl_workaround_enabled_82541(hw))) 212 goto out; 213 214 /* Check for link first */ 215 ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 216 if (ret_val) 217 goto out; 218 219 if (link) { 220 /* 221 * If link is established during the workaround, 222 * the DSP mechanism must be enabled. 223 */ 224 if (dev_spec->dsp_reset_counter) { 225 dev_spec->dsp_reset_counter = 0; 226 dsp_value = DSP_RESET_ENABLE; 227 } else { 228 ret_val = E1000_SUCCESS; 229 goto out; 230 } 231 } else { 232 if (dev_spec->dsp_reset_counter == 0) { 233 /* 234 * Workaround not activated, 235 * check if it needs activation 236 */ 237 ret_val = hw->phy.ops.read_reg(hw, 238 PHY_AUTONEG_EXP, 239 &phy_data); 240 if (ret_val) 241 goto out; 242 /* 243 * Activate the workaround if there was a 244 * parallel detect fault 245 */ 246 if (phy_data & NWAY_ER_PAR_DETECT_FAULT) { 247 dev_spec->dsp_reset_counter++; 248 } else { 249 ret_val = E1000_SUCCESS; 250 goto out; 251 } 252 } 253 254 /* After 5 times, stop the workaround */ 255 if (dev_spec->dsp_reset_counter > E1000_MAX_DSP_RESETS) { 256 dev_spec->dsp_reset_counter = 0; 257 dsp_value = DSP_RESET_ENABLE; 258 } else { 259 if (dev_spec->dsp_reset_counter) { 260 dsp_value = (dev_spec->dsp_reset_counter & 1) 261 ? DSP_RESET_DISABLE 262 : DSP_RESET_ENABLE; 263 dev_spec->dsp_reset_counter++; 264 } 265 } 266 } 267 268 ret_val = 269 hw->phy.ops.write_reg(hw, IGP01E1000_PHY_DSP_RESET, dsp_value); 270 271 out: 272 return (ret_val); 273 } 274