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 26/* 27 * IntelVersion: 1.27 v3-1-10-1_2009-9-18_Release14-6 28 */ 29 30#include "e1000_api.h" 31 32static u8 e1000_calculate_checksum(u8 *buffer, u32 length); 33 34/* 35 * e1000_calculate_checksum - Calculate checksum for buffer 36 * @buffer: pointer to EEPROM 37 * @length: size of EEPROM to calculate a checksum for 38 * 39 * Calculates the checksum for some buffer on a specified length. The 40 * checksum calculated is returned. 41 */ 42static u8 43e1000_calculate_checksum(u8 *buffer, u32 length) 44{ 45 u32 i; 46 u8 sum = 0; 47 48 DEBUGFUNC("e1000_calculate_checksum"); 49 50 if (!buffer) 51 return (0); 52 53 for (i = 0; i < length; i++) 54 sum += buffer[i]; 55 56 return (u8)(0 - sum); 57} 58 59/* 60 * e1000_mng_enable_host_if_generic - Checks host interface is enabled 61 * @hw: pointer to the HW structure 62 * 63 * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND 64 * 65 * This function checks whether the HOST IF is enabled for command operation 66 * and also checks whether the previous command is completed. It busy waits 67 * in case of previous command is not completed. 68 */ 69s32 70e1000_mng_enable_host_if_generic(struct e1000_hw *hw) 71{ 72 u32 hicr; 73 s32 ret_val = E1000_SUCCESS; 74 u8 i; 75 76 DEBUGFUNC("e1000_mng_enable_host_if_generic"); 77 78 /* Check that the host interface is enabled. */ 79 hicr = E1000_READ_REG(hw, E1000_HICR); 80 if ((hicr & E1000_HICR_EN) == 0) { 81 DEBUGOUT("E1000_HOST_EN bit disabled.\n"); 82 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 83 goto out; 84 } 85 /* check the previous command is completed */ 86 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { 87 hicr = E1000_READ_REG(hw, E1000_HICR); 88 if (!(hicr & E1000_HICR_C)) 89 break; 90 msec_delay_irq(1); 91 } 92 93 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 94 DEBUGOUT("Previous command timeout failed .\n"); 95 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 96 goto out; 97 } 98out: 99 return (ret_val); 100} 101 102/* 103 * e1000_check_mng_mode_generic - Generic check management mode 104 * @hw: pointer to the HW structure 105 * 106 * Reads the firmware semaphore register and returns true (>0) if 107 * manageability is enabled, else false (0). 108 */ 109bool 110e1000_check_mng_mode_generic(struct e1000_hw *hw) 111{ 112 u32 fwsm; 113 114 DEBUGFUNC("e1000_check_mng_mode_generic"); 115 116 fwsm = E1000_READ_REG(hw, E1000_FWSM); 117 118 return ((fwsm & E1000_FWSM_MODE_MASK) == 119 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); 120} 121 122/* 123 * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX 124 * @hw: pointer to the HW structure 125 * 126 * Enables packet filtering on transmit packets if manageability is enabled 127 * and host interface is enabled. 128 */ 129bool 130e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) 131{ 132 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; 133 u32 *buffer = (u32 *)&hw->mng_cookie; 134 u32 offset; 135 s32 ret_val, hdr_csum, csum; 136 u8 i, len; 137 bool tx_filter = true; 138 139 DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); 140 141 /* No manageability, no filtering */ 142 if (!hw->mac.ops.check_mng_mode(hw)) { 143 tx_filter = false; 144 goto out; 145 } 146 147 /* 148 * If we can't read from the host interface for whatever reason, 149 * disable filtering. 150 */ 151 ret_val = hw->mac.ops.mng_enable_host_if(hw); 152 if (ret_val != E1000_SUCCESS) { 153 tx_filter = false; 154 goto out; 155 } 156 157 /* Read in the header. Length and offset are in dwords. */ 158 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; 159 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; 160 for (i = 0; i < len; i++) { 161 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, 162 E1000_HOST_IF, 163 offset + i); 164 } 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 the cookie 171 * area isn't considered valid, in which case we take the safe route 172 * 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 183out: 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 */ 196s32 197e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, 198 u16 length) 199{ 200 struct e1000_host_mng_command_header hdr; 201 s32 ret_val; 202 u32 hicr; 203 204 DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); 205 206 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; 207 hdr.command_length = length; 208 hdr.reserved1 = 0; 209 hdr.reserved2 = 0; 210 hdr.checksum = 0; 211 212 /* Enable the host interface */ 213 ret_val = hw->mac.ops.mng_enable_host_if(hw); 214 if (ret_val) 215 goto out; 216 217 /* Populate the host interface with the contents of "buffer". */ 218 ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, 219 sizeof (hdr), &(hdr.checksum)); 220 if (ret_val) 221 goto out; 222 223 /* Write the manageability command header */ 224 ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); 225 if (ret_val) 226 goto out; 227 228 /* Tell the ARC a new command is pending. */ 229 hicr = E1000_READ_REG(hw, E1000_HICR); 230 E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 231 232out: 233 return (ret_val); 234} 235 236/* 237 * e1000_mng_write_cmd_header_generic - Writes manageability command header 238 * @hw: pointer to the HW structure 239 * @hdr: pointer to the host interface command header 240 * 241 * Writes the command header after does the checksum calculation. 242 */ 243s32 244e1000_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 *)(uintptr_t)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 */ 278s32 279e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, 280 u16 length, u16 offset, u8 *sum) 281{ 282 u8 *tmp; 283 u8 *bufptr = buffer; 284 u32 data = 0; 285 s32 ret_val = E1000_SUCCESS; 286 u16 remaining, i, j, prev_bytes; 287 288 DEBUGFUNC("e1000_mng_host_if_write_generic"); 289 290 /* sum = only sum of the data and it is not checksum */ 291 292 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { 293 ret_val = -E1000_ERR_PARAM; 294 goto out; 295 } 296 297 tmp = (u8 *)&data; 298 prev_bytes = offset & 0x3; 299 offset >>= 2; 300 301 if (prev_bytes) { 302 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); 303 for (j = prev_bytes; j < sizeof (u32); j++) { 304 *(tmp + j) = *bufptr++; 305 *sum += *(tmp + j); 306 } 307 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); 308 length -= j - prev_bytes; 309 offset++; 310 } 311 312 remaining = length & 0x3; 313 length -= remaining; 314 315 /* Calculate length in DWORDs */ 316 length >>= 2; 317 318 /* 319 * The device driver writes the relevant command block into the ram 320 * area. 321 */ 322 for (i = 0; i < length; i++) { 323 for (j = 0; j < sizeof (u32); j++) { 324 *(tmp + j) = *bufptr++; 325 *sum += *(tmp + j); 326 } 327 328 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 329 offset + i, data); 330 } 331 if (remaining) { 332 for (j = 0; j < sizeof (u32); j++) { 333 if (j < remaining) 334 *(tmp + j) = *bufptr++; 335 else 336 *(tmp + j) = 0; 337 338 *sum += *(tmp + j); 339 } 340 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 341 offset + i, data); 342 } 343out: 344 return (ret_val); 345} 346 347/* 348 * e1000_enable_mng_pass_thru - Enable processing of ARP's 349 * @hw: pointer to the HW structure 350 * 351 * Verifies the hardware needs to allow ARPs to be processed by the host. 352 */ 353bool 354e1000_enable_mng_pass_thru(struct e1000_hw *hw) 355{ 356 u32 manc; 357 u32 fwsm, factps; 358 bool ret_val = false; 359 360 DEBUGFUNC("e1000_enable_mng_pass_thru"); 361 362 if (!hw->mac.asf_firmware_present) 363 goto out; 364 365 manc = E1000_READ_REG(hw, E1000_MANC); 366 367 if (!(manc & E1000_MANC_RCV_TCO_EN) || 368 !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) 369 goto out; 370 371 if (hw->mac.arc_subsystem_valid) { 372 fwsm = E1000_READ_REG(hw, E1000_FWSM); 373 factps = E1000_READ_REG(hw, E1000_FACTPS); 374 375 if (!(factps & E1000_FACTPS_MNGCG) && 376 ((fwsm & E1000_FWSM_MODE_MASK) == 377 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { 378 ret_val = true; 379 goto out; 380 } 381 } else { 382 if ((manc & E1000_MANC_SMBUS_EN) && 383 !(manc & E1000_MANC_ASF_EN)) { 384 ret_val = true; 385 goto out; 386 } 387 } 388 389out: 390 return (ret_val); 391} 392