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 - 2008 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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms of the CDDLv1. 24 */ 25 26 /* 27 * IntelVersion: 1.21 v2008-02-29 28 */ 29 30 #include "e1000_api.h" 31 #include "e1000_manage.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 44 e1000_calculate_checksum(u8 *buffer, u32 length) 45 { 46 u32 i; 47 u8 sum = 0; 48 49 DEBUGFUNC("e1000_calculate_checksum"); 50 51 if (!buffer) 52 return (0); 53 54 for (i = 0; i < length; i++) 55 sum += buffer[i]; 56 57 return (u8)(0 - sum); 58 } 59 60 /* 61 * e1000_mng_enable_host_if_generic - Checks host interface is enabled 62 * @hw: pointer to the HW structure 63 * 64 * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND 65 * 66 * This function checks whether the HOST IF is enabled for command operation 67 * and also checks whether the previous command is completed. It busy waits 68 * in case of previous command is not completed. 69 */ 70 s32 71 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) 72 { 73 u32 hicr; 74 s32 ret_val = E1000_SUCCESS; 75 u8 i; 76 77 DEBUGFUNC("e1000_mng_enable_host_if_generic"); 78 79 /* Check that the host interface is enabled. */ 80 hicr = E1000_READ_REG(hw, E1000_HICR); 81 if ((hicr & E1000_HICR_EN) == 0) { 82 DEBUGOUT("E1000_HOST_EN bit disabled.\n"); 83 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 84 goto out; 85 } 86 /* check the previous command is completed */ 87 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { 88 hicr = E1000_READ_REG(hw, E1000_HICR); 89 if (!(hicr & E1000_HICR_C)) 90 break; 91 msec_delay_irq(1); 92 } 93 94 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 95 DEBUGOUT("Previous command timeout failed .\n"); 96 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 97 goto out; 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 reason, 150 * 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, 164 offset + i); 165 } 166 hdr_csum = hdr->checksum; 167 hdr->checksum = 0; 168 csum = e1000_calculate_checksum((u8 *)hdr, 169 E1000_MNG_DHCP_COOKIE_LENGTH); 170 /* 171 * If either the checksums or signature don't match, then the cookie 172 * area isn't considered valid, in which case we take the safe route 173 * of assuming Tx filtering is enabled. 174 */ 175 if (hdr_csum != csum) 176 goto out; 177 if (hdr->signature != E1000_IAMT_SIGNATURE) 178 goto out; 179 180 /* Cookie area is valid, make the final check for filtering. */ 181 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) 182 tx_filter = FALSE; 183 184 out: 185 hw->mac.tx_pkt_filtering = tx_filter; 186 return (tx_filter); 187 } 188 189 /* 190 * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface 191 * @hw: pointer to the HW structure 192 * @buffer: pointer to the host interface 193 * @length: size of the buffer 194 * 195 * Writes the DHCP information to the host interface. 196 */ 197 s32 198 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 245 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, 246 struct e1000_host_mng_command_header *hdr) 247 { 248 u16 i, length = sizeof (struct e1000_host_mng_command_header); 249 250 DEBUGFUNC("e1000_mng_write_cmd_header_generic"); 251 252 /* Write the whole command header structure with new checksum. */ 253 254 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); 255 256 length >>= 2; 257 /* Write the relevant command block into the ram area. */ 258 for (i = 0; i < length; i++) { 259 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, 260 *((u32 *)(uintptr_t)hdr + i)); 261 E1000_WRITE_FLUSH(hw); 262 } 263 264 return (E1000_SUCCESS); 265 } 266 267 /* 268 * e1000_mng_host_if_write_generic - Write to the manageability host interface 269 * @hw: pointer to the HW structure 270 * @buffer: pointer to the host interface buffer 271 * @length: size of the buffer 272 * @offset: location in the buffer to write to 273 * @sum: sum of the data (not checksum) 274 * 275 * This function writes the buffer content at the offset given on the host if. 276 * It also does alignment considerations to do the writes in most efficient 277 * way. Also fills up the sum of the buffer in *buffer parameter. 278 */ 279 s32 280 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, 281 u16 length, u16 offset, u8 *sum) 282 { 283 u8 *tmp; 284 u8 *bufptr = buffer; 285 u32 data = 0; 286 s32 ret_val = E1000_SUCCESS; 287 u16 remaining, i, j, prev_bytes; 288 289 DEBUGFUNC("e1000_mng_host_if_write_generic"); 290 291 /* sum = only sum of the data and it is not checksum */ 292 293 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { 294 ret_val = -E1000_ERR_PARAM; 295 goto out; 296 } 297 298 tmp = (u8 *)&data; 299 prev_bytes = offset & 0x3; 300 offset >>= 2; 301 302 if (prev_bytes) { 303 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); 304 for (j = prev_bytes; j < sizeof (u32); j++) { 305 *(tmp + j) = *bufptr++; 306 *sum += *(tmp + j); 307 } 308 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); 309 length -= j - prev_bytes; 310 offset++; 311 } 312 313 remaining = length & 0x3; 314 length -= remaining; 315 316 /* Calculate length in DWORDs */ 317 length >>= 2; 318 319 /* 320 * The device driver writes the relevant command block into the ram 321 * area. 322 */ 323 for (i = 0; i < length; i++) { 324 for (j = 0; j < sizeof (u32); j++) { 325 *(tmp + j) = *bufptr++; 326 *sum += *(tmp + j); 327 } 328 329 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 330 offset + i, data); 331 } 332 if (remaining) { 333 for (j = 0; j < sizeof (u32); j++) { 334 if (j < remaining) 335 *(tmp + j) = *bufptr++; 336 else 337 *(tmp + j) = 0; 338 339 *sum += *(tmp + j); 340 } 341 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 342 offset + i, data); 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