1 /****************************************************************************** 2 3 Copyright (c) 2001-2010, Intel Corporation 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions are met: 8 9 1. Redistributions of source code must retain the above copyright notice, 10 this list of conditions and the following disclaimer. 11 12 2. Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in the 14 documentation and/or other materials provided with the distribution. 15 16 3. Neither the name of the Intel Corporation nor the names of its 17 contributors may be used to endorse or promote products derived from 18 this software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 POSSIBILITY OF SUCH DAMAGE. 31 32 ******************************************************************************/ 33 /*$FreeBSD$*/ 34 35 #include "e1000_api.h" 36 37 static u8 e1000_calculate_checksum(u8 *buffer, u32 length); 38 39 /** 40 * e1000_calculate_checksum - Calculate checksum for buffer 41 * @buffer: pointer to EEPROM 42 * @length: size of EEPROM to calculate a checksum for 43 * 44 * Calculates the checksum for some buffer on a specified length. The 45 * checksum calculated is returned. 46 **/ 47 static u8 e1000_calculate_checksum(u8 *buffer, u32 length) 48 { 49 u32 i; 50 u8 sum = 0; 51 52 DEBUGFUNC("e1000_calculate_checksum"); 53 54 if (!buffer) 55 return 0; 56 57 for (i = 0; i < length; i++) 58 sum += buffer[i]; 59 60 return (u8) (0 - sum); 61 } 62 63 /** 64 * e1000_mng_enable_host_if_generic - Checks host interface is enabled 65 * @hw: pointer to the HW structure 66 * 67 * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND 68 * 69 * This function checks whether the HOST IF is enabled for command operation 70 * and also checks whether the previous command is completed. It busy waits 71 * in case of previous command is not completed. 72 **/ 73 s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) 74 { 75 u32 hicr; 76 s32 ret_val = E1000_SUCCESS; 77 u8 i; 78 79 DEBUGFUNC("e1000_mng_enable_host_if_generic"); 80 81 if (!(hw->mac.arc_subsystem_valid)) { 82 DEBUGOUT("ARC subsystem not valid.\n"); 83 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 84 goto out; 85 } 86 87 /* Check that the host interface is enabled. */ 88 hicr = E1000_READ_REG(hw, E1000_HICR); 89 if ((hicr & E1000_HICR_EN) == 0) { 90 DEBUGOUT("E1000_HOST_EN bit disabled.\n"); 91 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 92 goto out; 93 } 94 /* check the previous command is completed */ 95 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { 96 hicr = E1000_READ_REG(hw, E1000_HICR); 97 if (!(hicr & E1000_HICR_C)) 98 break; 99 msec_delay_irq(1); 100 } 101 102 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 103 DEBUGOUT("Previous command timeout failed .\n"); 104 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 105 goto out; 106 } 107 108 out: 109 return ret_val; 110 } 111 112 /** 113 * e1000_check_mng_mode_generic - Generic check management mode 114 * @hw: pointer to the HW structure 115 * 116 * Reads the firmware semaphore register and returns TRUE (>0) if 117 * manageability is enabled, else FALSE (0). 118 **/ 119 bool e1000_check_mng_mode_generic(struct e1000_hw *hw) 120 { 121 u32 fwsm = E1000_READ_REG(hw, E1000_FWSM); 122 123 DEBUGFUNC("e1000_check_mng_mode_generic"); 124 125 126 return (fwsm & E1000_FWSM_MODE_MASK) == 127 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); 128 } 129 130 /** 131 * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx 132 * @hw: pointer to the HW structure 133 * 134 * Enables packet filtering on transmit packets if manageability is enabled 135 * and host interface is enabled. 136 **/ 137 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) 138 { 139 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; 140 u32 *buffer = (u32 *)&hw->mng_cookie; 141 u32 offset; 142 s32 ret_val, hdr_csum, csum; 143 u8 i, len; 144 145 DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); 146 147 hw->mac.tx_pkt_filtering = TRUE; 148 149 /* No manageability, no filtering */ 150 if (!hw->mac.ops.check_mng_mode(hw)) { 151 hw->mac.tx_pkt_filtering = FALSE; 152 goto out; 153 } 154 155 /* 156 * If we can't read from the host interface for whatever 157 * reason, disable filtering. 158 */ 159 ret_val = hw->mac.ops.mng_enable_host_if(hw); 160 if (ret_val != E1000_SUCCESS) { 161 hw->mac.tx_pkt_filtering = FALSE; 162 goto out; 163 } 164 165 /* Read in the header. Length and offset are in dwords. */ 166 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; 167 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; 168 for (i = 0; i < len; i++) 169 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 170 offset + i); 171 hdr_csum = hdr->checksum; 172 hdr->checksum = 0; 173 csum = e1000_calculate_checksum((u8 *)hdr, 174 E1000_MNG_DHCP_COOKIE_LENGTH); 175 /* 176 * If either the checksums or signature don't match, then 177 * the cookie area isn't considered valid, in which case we 178 * take the safe route of assuming Tx filtering is enabled. 179 */ 180 if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { 181 hw->mac.tx_pkt_filtering = TRUE; 182 goto out; 183 } 184 185 /* Cookie area is valid, make the final check for filtering. */ 186 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) { 187 hw->mac.tx_pkt_filtering = FALSE; 188 goto out; 189 } 190 191 out: 192 return hw->mac.tx_pkt_filtering; 193 } 194 195 /** 196 * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface 197 * @hw: pointer to the HW structure 198 * @buffer: pointer to the host interface 199 * @length: size of the buffer 200 * 201 * Writes the DHCP information to the host interface. 202 **/ 203 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, 204 u16 length) 205 { 206 struct e1000_host_mng_command_header hdr; 207 s32 ret_val; 208 u32 hicr; 209 210 DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); 211 212 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; 213 hdr.command_length = length; 214 hdr.reserved1 = 0; 215 hdr.reserved2 = 0; 216 hdr.checksum = 0; 217 218 /* Enable the host interface */ 219 ret_val = hw->mac.ops.mng_enable_host_if(hw); 220 if (ret_val) 221 goto out; 222 223 /* Populate the host interface with the contents of "buffer". */ 224 ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, 225 sizeof(hdr), &(hdr.checksum)); 226 if (ret_val) 227 goto out; 228 229 /* Write the manageability command header */ 230 ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); 231 if (ret_val) 232 goto out; 233 234 /* Tell the ARC a new command is pending. */ 235 hicr = E1000_READ_REG(hw, E1000_HICR); 236 E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 237 238 out: 239 return ret_val; 240 } 241 242 /** 243 * e1000_mng_write_cmd_header_generic - Writes manageability command header 244 * @hw: pointer to the HW structure 245 * @hdr: pointer to the host interface command header 246 * 247 * Writes the command header after does the checksum calculation. 248 **/ 249 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, 250 struct e1000_host_mng_command_header *hdr) 251 { 252 u16 i, length = sizeof(struct e1000_host_mng_command_header); 253 254 DEBUGFUNC("e1000_mng_write_cmd_header_generic"); 255 256 /* Write the whole command header structure with new checksum. */ 257 258 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); 259 260 length >>= 2; 261 /* Write the relevant command block into the ram area. */ 262 for (i = 0; i < length; i++) { 263 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, 264 *((u32 *) hdr + i)); 265 E1000_WRITE_FLUSH(hw); 266 } 267 268 return E1000_SUCCESS; 269 } 270 271 /** 272 * e1000_mng_host_if_write_generic - Write to the manageability host interface 273 * @hw: pointer to the HW structure 274 * @buffer: pointer to the host interface buffer 275 * @length: size of the buffer 276 * @offset: location in the buffer to write to 277 * @sum: sum of the data (not checksum) 278 * 279 * This function writes the buffer content at the offset given on the host if. 280 * It also does alignment considerations to do the writes in most efficient 281 * way. Also fills up the sum of the buffer in *buffer parameter. 282 **/ 283 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, 284 u16 length, u16 offset, u8 *sum) 285 { 286 u8 *tmp; 287 u8 *bufptr = buffer; 288 u32 data = 0; 289 s32 ret_val = E1000_SUCCESS; 290 u16 remaining, i, j, prev_bytes; 291 292 DEBUGFUNC("e1000_mng_host_if_write_generic"); 293 294 /* sum = only sum of the data and it is not checksum */ 295 296 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { 297 ret_val = -E1000_ERR_PARAM; 298 goto out; 299 } 300 301 tmp = (u8 *)&data; 302 prev_bytes = offset & 0x3; 303 offset >>= 2; 304 305 if (prev_bytes) { 306 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); 307 for (j = prev_bytes; j < sizeof(u32); j++) { 308 *(tmp + j) = *bufptr++; 309 *sum += *(tmp + j); 310 } 311 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); 312 length -= j - prev_bytes; 313 offset++; 314 } 315 316 remaining = length & 0x3; 317 length -= remaining; 318 319 /* Calculate length in DWORDs */ 320 length >>= 2; 321 322 /* 323 * The device driver writes the relevant command block into the 324 * ram area. 325 */ 326 for (i = 0; i < length; i++) { 327 for (j = 0; j < sizeof(u32); j++) { 328 *(tmp + j) = *bufptr++; 329 *sum += *(tmp + j); 330 } 331 332 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, 333 data); 334 } 335 if (remaining) { 336 for (j = 0; j < sizeof(u32); j++) { 337 if (j < remaining) 338 *(tmp + j) = *bufptr++; 339 else 340 *(tmp + j) = 0; 341 342 *sum += *(tmp + j); 343 } 344 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); 345 } 346 347 out: 348 return ret_val; 349 } 350 351 /** 352 * e1000_enable_mng_pass_thru - Check if management passthrough is needed 353 * @hw: pointer to the HW structure 354 * 355 * Verifies the hardware needs to leave interface enabled so that frames can 356 * be directed to and from the management interface. 357 **/ 358 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) 359 { 360 u32 manc; 361 u32 fwsm, factps; 362 bool ret_val = FALSE; 363 364 DEBUGFUNC("e1000_enable_mng_pass_thru"); 365 366 if (!hw->mac.asf_firmware_present) 367 goto out; 368 369 manc = E1000_READ_REG(hw, E1000_MANC); 370 371 if (!(manc & E1000_MANC_RCV_TCO_EN)) 372 goto out; 373 374 if (hw->mac.has_fwsm) { 375 fwsm = E1000_READ_REG(hw, E1000_FWSM); 376 factps = E1000_READ_REG(hw, E1000_FACTPS); 377 378 if (!(factps & E1000_FACTPS_MNGCG) && 379 ((fwsm & E1000_FWSM_MODE_MASK) == 380 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { 381 ret_val = TRUE; 382 goto out; 383 } 384 } else if ((hw->mac.type == e1000_82574) || 385 (hw->mac.type == e1000_82583)) { 386 u16 data; 387 388 factps = E1000_READ_REG(hw, E1000_FACTPS); 389 e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); 390 391 if (!(factps & E1000_FACTPS_MNGCG) && 392 ((data & E1000_NVM_INIT_CTRL2_MNGM) == 393 (e1000_mng_mode_pt << 13))) { 394 ret_val = TRUE; 395 goto out; 396 } 397 } else if ((manc & E1000_MANC_SMBUS_EN) && 398 !(manc & E1000_MANC_ASF_EN)) { 399 ret_val = TRUE; 400 goto out; 401 } 402 403 out: 404 return ret_val; 405 } 406 407