1 /****************************************************************************** 2 3 Copyright (c) 2001-2009, 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, E1000_HOST_IF, 164 offset + i); 165 hdr_csum = hdr->checksum; 166 hdr->checksum = 0; 167 csum = e1000_calculate_checksum((u8 *)hdr, 168 E1000_MNG_DHCP_COOKIE_LENGTH); 169 /* 170 * If either the checksums or signature don't match, then 171 * the cookie area isn't considered valid, in which case we 172 * take the safe route of assuming Tx filtering is enabled. 173 */ 174 if (hdr_csum != csum) 175 goto out; 176 if (hdr->signature != E1000_IAMT_SIGNATURE) 177 goto out; 178 179 /* Cookie area is valid, make the final check for filtering. */ 180 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) 181 tx_filter = FALSE; 182 183 out: 184 hw->mac.tx_pkt_filtering = tx_filter; 185 return tx_filter; 186 } 187 188 /** 189 * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface 190 * @hw: pointer to the HW structure 191 * @buffer: pointer to the host interface 192 * @length: size of the buffer 193 * 194 * Writes the DHCP information to the host interface. 195 **/ 196 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, 197 u16 length) 198 { 199 struct e1000_host_mng_command_header hdr; 200 s32 ret_val; 201 u32 hicr; 202 203 DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); 204 205 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; 206 hdr.command_length = length; 207 hdr.reserved1 = 0; 208 hdr.reserved2 = 0; 209 hdr.checksum = 0; 210 211 /* Enable the host interface */ 212 ret_val = hw->mac.ops.mng_enable_host_if(hw); 213 if (ret_val) 214 goto out; 215 216 /* Populate the host interface with the contents of "buffer". */ 217 ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, 218 sizeof(hdr), &(hdr.checksum)); 219 if (ret_val) 220 goto out; 221 222 /* Write the manageability command header */ 223 ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); 224 if (ret_val) 225 goto out; 226 227 /* Tell the ARC a new command is pending. */ 228 hicr = E1000_READ_REG(hw, E1000_HICR); 229 E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 230 231 out: 232 return ret_val; 233 } 234 235 /** 236 * e1000_mng_write_cmd_header_generic - Writes manageability command header 237 * @hw: pointer to the HW structure 238 * @hdr: pointer to the host interface command header 239 * 240 * Writes the command header after does the checksum calculation. 241 **/ 242 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, 243 struct e1000_host_mng_command_header *hdr) 244 { 245 u16 i, length = sizeof(struct e1000_host_mng_command_header); 246 247 DEBUGFUNC("e1000_mng_write_cmd_header_generic"); 248 249 /* Write the whole command header structure with new checksum. */ 250 251 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); 252 253 length >>= 2; 254 /* Write the relevant command block into the ram area. */ 255 for (i = 0; i < length; i++) { 256 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, 257 *((u32 *) hdr + i)); 258 E1000_WRITE_FLUSH(hw); 259 } 260 261 return E1000_SUCCESS; 262 } 263 264 /** 265 * e1000_mng_host_if_write_generic - Write to the manageability host interface 266 * @hw: pointer to the HW structure 267 * @buffer: pointer to the host interface buffer 268 * @length: size of the buffer 269 * @offset: location in the buffer to write to 270 * @sum: sum of the data (not checksum) 271 * 272 * This function writes the buffer content at the offset given on the host if. 273 * It also does alignment considerations to do the writes in most efficient 274 * way. Also fills up the sum of the buffer in *buffer parameter. 275 **/ 276 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, 277 u16 length, u16 offset, u8 *sum) 278 { 279 u8 *tmp; 280 u8 *bufptr = buffer; 281 u32 data = 0; 282 s32 ret_val = E1000_SUCCESS; 283 u16 remaining, i, j, prev_bytes; 284 285 DEBUGFUNC("e1000_mng_host_if_write_generic"); 286 287 /* sum = only sum of the data and it is not checksum */ 288 289 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { 290 ret_val = -E1000_ERR_PARAM; 291 goto out; 292 } 293 294 tmp = (u8 *)&data; 295 prev_bytes = offset & 0x3; 296 offset >>= 2; 297 298 if (prev_bytes) { 299 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); 300 for (j = prev_bytes; j < sizeof(u32); j++) { 301 *(tmp + j) = *bufptr++; 302 *sum += *(tmp + j); 303 } 304 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); 305 length -= j - prev_bytes; 306 offset++; 307 } 308 309 remaining = length & 0x3; 310 length -= remaining; 311 312 /* Calculate length in DWORDs */ 313 length >>= 2; 314 315 /* 316 * The device driver writes the relevant command block into the 317 * ram area. 318 */ 319 for (i = 0; i < length; i++) { 320 for (j = 0; j < sizeof(u32); j++) { 321 *(tmp + j) = *bufptr++; 322 *sum += *(tmp + j); 323 } 324 325 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, 326 data); 327 } 328 if (remaining) { 329 for (j = 0; j < sizeof(u32); j++) { 330 if (j < remaining) 331 *(tmp + j) = *bufptr++; 332 else 333 *(tmp + j) = 0; 334 335 *sum += *(tmp + j); 336 } 337 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data); 338 } 339 340 out: 341 return ret_val; 342 } 343 344 /** 345 * e1000_enable_mng_pass_thru - Enable processing of ARP's 346 * @hw: pointer to the HW structure 347 * 348 * Verifies the hardware needs to allow ARPs to be processed by the host. 349 **/ 350 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) 351 { 352 u32 manc; 353 u32 fwsm, factps; 354 bool ret_val = FALSE; 355 356 DEBUGFUNC("e1000_enable_mng_pass_thru"); 357 358 if (!hw->mac.asf_firmware_present) 359 goto out; 360 361 manc = E1000_READ_REG(hw, E1000_MANC); 362 363 if (!(manc & E1000_MANC_RCV_TCO_EN) || 364 !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) 365 goto out; 366 367 if (hw->mac.arc_subsystem_valid) { 368 fwsm = E1000_READ_REG(hw, E1000_FWSM); 369 factps = E1000_READ_REG(hw, E1000_FACTPS); 370 371 if (!(factps & E1000_FACTPS_MNGCG) && 372 ((fwsm & E1000_FWSM_MODE_MASK) == 373 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { 374 ret_val = TRUE; 375 goto out; 376 } 377 } else { 378 if ((manc & E1000_MANC_SMBUS_EN) && 379 !(manc & E1000_MANC_ASF_EN)) { 380 ret_val = TRUE; 381 goto out; 382 } 383 } 384 385 out: 386 return ret_val; 387 } 388 389