1 /* 2 * CDDL HEADER START 3 * 4 * Copyright(c) 2007-2009 Intel Corporation. All rights reserved. 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at: 10 * http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When using or redistributing this file, you may do so under the 15 * License only. No other modification of this header is permitted. 16 * 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 */ 23 24 /* 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms of the CDDL. 27 */ 28 29 /* IntelVersion: 1.27 v2008-10-7 */ 30 31 #include "igb_api.h" 32 33 static u8 e1000_calculate_checksum(u8 *buffer, u32 length); 34 35 /* 36 * e1000_calculate_checksum - Calculate checksum for buffer 37 * @buffer: pointer to EEPROM 38 * @length: size of EEPROM to calculate a checksum for 39 * 40 * Calculates the checksum for some buffer on a specified length. The 41 * checksum calculated is returned. 42 */ 43 static u8 e1000_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 */ 69 s32 70 e1000_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 } 98 99 out: 100 return (ret_val); 101 } 102 103 /* 104 * e1000_check_mng_mode_generic - Generic check management mode 105 * @hw: pointer to the HW structure 106 * 107 * Reads the firmware semaphore register and returns true (>0) if 108 * manageability is enabled, else false (0). 109 */ 110 bool 111 e1000_check_mng_mode_generic(struct e1000_hw *hw) 112 { 113 u32 fwsm; 114 115 DEBUGFUNC("e1000_check_mng_mode_generic"); 116 117 fwsm = E1000_READ_REG(hw, E1000_FWSM); 118 119 return ((fwsm & E1000_FWSM_MODE_MASK) == 120 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); 121 } 122 123 /* 124 * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX 125 * @hw: pointer to the HW structure 126 * 127 * Enables packet filtering on transmit packets if manageability is enabled 128 * and host interface is enabled. 129 */ 130 bool 131 e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) 132 { 133 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; 134 u32 *buffer = (u32 *)&hw->mng_cookie; 135 u32 offset; 136 s32 ret_val, hdr_csum, csum; 137 u8 i, len; 138 bool tx_filter = true; 139 140 DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); 141 142 /* No manageability, no filtering */ 143 if (!hw->mac.ops.check_mng_mode(hw)) { 144 tx_filter = false; 145 goto out; 146 } 147 148 /* 149 * If we can't read from the host interface for whatever 150 * reason, disable filtering. 151 */ 152 ret_val = hw->mac.ops.mng_enable_host_if(hw); 153 if (ret_val != E1000_SUCCESS) { 154 tx_filter = false; 155 goto out; 156 } 157 158 /* Read in the header. Length and offset are in dwords. */ 159 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; 160 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; 161 for (i = 0; i < len; i++) { 162 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, 163 E1000_HOST_IF, 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 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 197 e1000_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 232 out: 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 */ 243 s32 244 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 *)(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 */ 278 s32 279 e1000_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 320 * ram 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 } 343 344 out: 345 return (ret_val); 346 } 347 348 /* 349 * e1000_enable_mng_pass_thru - Enable processing of ARP's 350 * @hw: pointer to the HW structure 351 * 352 * Verifies the hardware needs to allow ARPs to be processed by the host. 353 */ 354 bool 355 e1000_enable_mng_pass_thru(struct e1000_hw *hw) 356 { 357 u32 manc; 358 u32 fwsm, factps; 359 bool ret_val = false; 360 361 DEBUGFUNC("e1000_enable_mng_pass_thru"); 362 363 if (!hw->mac.asf_firmware_present) 364 goto out; 365 366 manc = E1000_READ_REG(hw, E1000_MANC); 367 368 if (!(manc & E1000_MANC_RCV_TCO_EN) || 369 !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) 370 goto out; 371 372 if (hw->mac.arc_subsystem_valid) { 373 fwsm = E1000_READ_REG(hw, E1000_FWSM); 374 factps = E1000_READ_REG(hw, E1000_FACTPS); 375 376 if (!(factps & E1000_FACTPS_MNGCG) && 377 ((fwsm & E1000_FWSM_MODE_MASK) == 378 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { 379 ret_val = true; 380 goto out; 381 } 382 } else { 383 if ((manc & E1000_MANC_SMBUS_EN) && 384 !(manc & E1000_MANC_ASF_EN)) { 385 ret_val = true; 386 goto out; 387 } 388 } 389 390 out: 391 return (ret_val); 392 } 393