1 /****************************************************************************** 2 3 Copyright (c) 2001-2008, 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 /* Check that the host interface is enabled. */ 82 hicr = E1000_READ_REG(hw, E1000_HICR); 83 if ((hicr & E1000_HICR_EN) == 0) { 84 DEBUGOUT("E1000_HOST_EN bit disabled.\n"); 85 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 86 goto out; 87 } 88 /* check the previous command is completed */ 89 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { 90 hicr = E1000_READ_REG(hw, E1000_HICR); 91 if (!(hicr & E1000_HICR_C)) 92 break; 93 msec_delay_irq(1); 94 } 95 96 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 97 DEBUGOUT("Previous command timeout failed .\n"); 98 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 99 goto out; 100 } 101 102 out: 103 return ret_val; 104 } 105 106 /** 107 * e1000_check_mng_mode_generic - Generic check management mode 108 * @hw: pointer to the HW structure 109 * 110 * Reads the firmware semaphore register and returns TRUE (>0) if 111 * manageability is enabled, else FALSE (0). 112 **/ 113 bool e1000_check_mng_mode_generic(struct e1000_hw *hw) 114 { 115 u32 fwsm; 116 117 DEBUGFUNC("e1000_check_mng_mode_generic"); 118 119 fwsm = E1000_READ_REG(hw, E1000_FWSM); 120 121 return (fwsm & E1000_FWSM_MODE_MASK) == 122 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); 123 } 124 125 /** 126 * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX 127 * @hw: pointer to the HW structure 128 * 129 * Enables packet filtering on transmit packets if manageability is enabled 130 * and host interface is enabled. 131 **/ 132 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) 133 { 134 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; 135 u32 *buffer = (u32 *)&hw->mng_cookie; 136 u32 offset; 137 s32 ret_val, hdr_csum, csum; 138 u8 i, len; 139 bool tx_filter = TRUE; 140 141 DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); 142 143 /* No manageability, no filtering */ 144 if (!hw->mac.ops.check_mng_mode(hw)) { 145 tx_filter = FALSE; 146 goto out; 147 } 148 149 /* 150 * If we can't read from the host interface for whatever 151 * reason, disable filtering. 152 */ 153 ret_val = hw->mac.ops.mng_enable_host_if(hw); 154 if (ret_val != E1000_SUCCESS) { 155 tx_filter = FALSE; 156 goto out; 157 } 158 159 /* Read in the header. Length and offset are in dwords. */ 160 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; 161 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; 162 for (i = 0; i < len; i++) { 163 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, 164 E1000_HOST_IF, 165 offset + i); 166 } 167 hdr_csum = hdr->checksum; 168 hdr->checksum = 0; 169 csum = e1000_calculate_checksum((u8 *)hdr, 170 E1000_MNG_DHCP_COOKIE_LENGTH); 171 /* 172 * If either the checksums or signature don't match, then 173 * the cookie area isn't considered valid, in which case we 174 * take the safe route of assuming Tx filtering is enabled. 175 */ 176 if (hdr_csum != csum) 177 goto out; 178 if (hdr->signature != E1000_IAMT_SIGNATURE) 179 goto out; 180 181 /* Cookie area is valid, make the final check for filtering. */ 182 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) 183 tx_filter = FALSE; 184 185 out: 186 hw->mac.tx_pkt_filtering = tx_filter; 187 return tx_filter; 188 } 189 190 /** 191 * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface 192 * @hw: pointer to the HW structure 193 * @buffer: pointer to the host interface 194 * @length: size of the buffer 195 * 196 * Writes the DHCP information to the host interface. 197 **/ 198 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, 199 u16 length) 200 { 201 struct e1000_host_mng_command_header hdr; 202 s32 ret_val; 203 u32 hicr; 204 205 DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); 206 207 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; 208 hdr.command_length = length; 209 hdr.reserved1 = 0; 210 hdr.reserved2 = 0; 211 hdr.checksum = 0; 212 213 /* Enable the host interface */ 214 ret_val = hw->mac.ops.mng_enable_host_if(hw); 215 if (ret_val) 216 goto out; 217 218 /* Populate the host interface with the contents of "buffer". */ 219 ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, 220 sizeof(hdr), &(hdr.checksum)); 221 if (ret_val) 222 goto out; 223 224 /* Write the manageability command header */ 225 ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); 226 if (ret_val) 227 goto out; 228 229 /* Tell the ARC a new command is pending. */ 230 hicr = E1000_READ_REG(hw, E1000_HICR); 231 E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 232 233 out: 234 return ret_val; 235 } 236 237 /** 238 * e1000_mng_write_cmd_header_generic - Writes manageability command header 239 * @hw: pointer to the HW structure 240 * @hdr: pointer to the host interface command header 241 * 242 * Writes the command header after does the checksum calculation. 243 **/ 244 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, 245 struct e1000_host_mng_command_header *hdr) 246 { 247 u16 i, length = sizeof(struct e1000_host_mng_command_header); 248 249 DEBUGFUNC("e1000_mng_write_cmd_header_generic"); 250 251 /* Write the whole command header structure with new checksum. */ 252 253 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); 254 255 length >>= 2; 256 /* Write the relevant command block into the ram area. */ 257 for (i = 0; i < length; i++) { 258 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, 259 *((u32 *) hdr + i)); 260 E1000_WRITE_FLUSH(hw); 261 } 262 263 return E1000_SUCCESS; 264 } 265 266 /** 267 * e1000_mng_host_if_write_generic - Write to the manageability host interface 268 * @hw: pointer to the HW structure 269 * @buffer: pointer to the host interface buffer 270 * @length: size of the buffer 271 * @offset: location in the buffer to write to 272 * @sum: sum of the data (not checksum) 273 * 274 * This function writes the buffer content at the offset given on the host if. 275 * It also does alignment considerations to do the writes in most efficient 276 * way. Also fills up the sum of the buffer in *buffer parameter. 277 **/ 278 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, 279 u16 length, u16 offset, u8 *sum) 280 { 281 u8 *tmp; 282 u8 *bufptr = buffer; 283 u32 data = 0; 284 s32 ret_val = E1000_SUCCESS; 285 u16 remaining, i, j, prev_bytes; 286 287 DEBUGFUNC("e1000_mng_host_if_write_generic"); 288 289 /* sum = only sum of the data and it is not checksum */ 290 291 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { 292 ret_val = -E1000_ERR_PARAM; 293 goto out; 294 } 295 296 tmp = (u8 *)&data; 297 prev_bytes = offset & 0x3; 298 offset >>= 2; 299 300 if (prev_bytes) { 301 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); 302 for (j = prev_bytes; j < sizeof(u32); j++) { 303 *(tmp + j) = *bufptr++; 304 *sum += *(tmp + j); 305 } 306 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); 307 length -= j - prev_bytes; 308 offset++; 309 } 310 311 remaining = length & 0x3; 312 length -= remaining; 313 314 /* Calculate length in DWORDs */ 315 length >>= 2; 316 317 /* 318 * The device driver writes the relevant command block into the 319 * ram area. 320 */ 321 for (i = 0; i < length; i++) { 322 for (j = 0; j < sizeof(u32); j++) { 323 *(tmp + j) = *bufptr++; 324 *sum += *(tmp + j); 325 } 326 327 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, 328 data); 329 } 330 if (remaining) { 331 for (j = 0; j < sizeof(u32); j++) { 332 if (j < remaining) 333 *(tmp + j) = *bufptr++; 334 else 335 *(tmp + j) = 0; 336 337 *sum += *(tmp + j); 338 } 339 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); 340 } 341 342 out: 343 return ret_val; 344 } 345 346 /** 347 * e1000_enable_mng_pass_thru - Enable processing of ARP's 348 * @hw: pointer to the HW structure 349 * 350 * Verifies the hardware needs to allow ARPs to be processed by the host. 351 **/ 352 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) 353 { 354 u32 manc; 355 u32 fwsm, factps; 356 bool ret_val = FALSE; 357 358 DEBUGFUNC("e1000_enable_mng_pass_thru"); 359 360 if (!hw->mac.asf_firmware_present) 361 goto out; 362 363 manc = E1000_READ_REG(hw, E1000_MANC); 364 365 if (!(manc & E1000_MANC_RCV_TCO_EN) || 366 !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) 367 goto out; 368 369 if (hw->mac.arc_subsystem_valid) { 370 fwsm = E1000_READ_REG(hw, E1000_FWSM); 371 factps = E1000_READ_REG(hw, E1000_FACTPS); 372 373 if (!(factps & E1000_FACTPS_MNGCG) && 374 ((fwsm & E1000_FWSM_MODE_MASK) == 375 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { 376 ret_val = TRUE; 377 goto out; 378 } 379 } else { 380 if ((manc & E1000_MANC_SMBUS_EN) && 381 !(manc & E1000_MANC_ASF_EN)) { 382 ret_val = TRUE; 383 goto out; 384 } 385 } 386 387 out: 388 return ret_val; 389 } 390 391