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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * IntelVersion: 1.21 v2008-02-29 30 */ 31 32 #include "e1000_api.h" 33 #include "e1000_manage.h" 34 35 static u8 e1000_calculate_checksum(u8 *buffer, u32 length); 36 37 /* 38 * e1000_calculate_checksum - Calculate checksum for buffer 39 * @buffer: pointer to EEPROM 40 * @length: size of EEPROM to calculate a checksum for 41 * 42 * Calculates the checksum for some buffer on a specified length. The 43 * checksum calculated is returned. 44 */ 45 static u8 46 e1000_calculate_checksum(u8 *buffer, u32 length) 47 { 48 u32 i; 49 u8 sum = 0; 50 51 DEBUGFUNC("e1000_calculate_checksum"); 52 53 if (!buffer) 54 return (0); 55 56 for (i = 0; i < length; i++) 57 sum += buffer[i]; 58 59 return (u8)(0 - sum); 60 } 61 62 /* 63 * e1000_mng_enable_host_if_generic - Checks host interface is enabled 64 * @hw: pointer to the HW structure 65 * 66 * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND 67 * 68 * This function checks whether the HOST IF is enabled for command operation 69 * and also checks whether the previous command is completed. It busy waits 70 * in case of previous command is not completed. 71 */ 72 s32 73 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 out: 102 return (ret_val); 103 } 104 105 /* 106 * e1000_check_mng_mode_generic - Generic check management mode 107 * @hw: pointer to the HW structure 108 * 109 * Reads the firmware semaphore register and returns true (>0) if 110 * manageability is enabled, else false (0). 111 */ 112 bool 113 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 133 e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) 134 { 135 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; 136 u32 *buffer = (u32 *)&hw->mng_cookie; 137 u32 offset; 138 s32 ret_val, hdr_csum, csum; 139 u8 i, len; 140 bool tx_filter = TRUE; 141 142 DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); 143 144 /* No manageability, no filtering */ 145 if (!hw->mac.ops.check_mng_mode(hw)) { 146 tx_filter = FALSE; 147 goto out; 148 } 149 150 /* 151 * If we can't read from the host interface for whatever reason, 152 * disable filtering. 153 */ 154 ret_val = hw->mac.ops.mng_enable_host_if(hw); 155 if (ret_val != E1000_SUCCESS) { 156 tx_filter = FALSE; 157 goto out; 158 } 159 160 /* Read in the header. Length and offset are in dwords. */ 161 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; 162 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; 163 for (i = 0; i < len; i++) { 164 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, 165 E1000_HOST_IF, 166 offset + i); 167 } 168 hdr_csum = hdr->checksum; 169 hdr->checksum = 0; 170 csum = e1000_calculate_checksum((u8 *)hdr, 171 E1000_MNG_DHCP_COOKIE_LENGTH); 172 /* 173 * If either the checksums or signature don't match, then the cookie 174 * area isn't considered valid, in which case we take the safe route 175 * of assuming Tx filtering is enabled. 176 */ 177 if (hdr_csum != csum) 178 goto out; 179 if (hdr->signature != E1000_IAMT_SIGNATURE) 180 goto out; 181 182 /* Cookie area is valid, make the final check for filtering. */ 183 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) 184 tx_filter = FALSE; 185 186 out: 187 hw->mac.tx_pkt_filtering = tx_filter; 188 return (tx_filter); 189 } 190 191 /* 192 * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface 193 * @hw: pointer to the HW structure 194 * @buffer: pointer to the host interface 195 * @length: size of the buffer 196 * 197 * Writes the DHCP information to the host interface. 198 */ 199 s32 200 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, 201 u16 length) 202 { 203 struct e1000_host_mng_command_header hdr; 204 s32 ret_val; 205 u32 hicr; 206 207 DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); 208 209 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; 210 hdr.command_length = length; 211 hdr.reserved1 = 0; 212 hdr.reserved2 = 0; 213 hdr.checksum = 0; 214 215 /* Enable the host interface */ 216 ret_val = hw->mac.ops.mng_enable_host_if(hw); 217 if (ret_val) 218 goto out; 219 220 /* Populate the host interface with the contents of "buffer". */ 221 ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length, 222 sizeof (hdr), &(hdr.checksum)); 223 if (ret_val) 224 goto out; 225 226 /* Write the manageability command header */ 227 ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr); 228 if (ret_val) 229 goto out; 230 231 /* Tell the ARC a new command is pending. */ 232 hicr = E1000_READ_REG(hw, E1000_HICR); 233 E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 234 235 out: 236 return (ret_val); 237 } 238 239 /* 240 * e1000_mng_write_cmd_header_generic - Writes manageability command header 241 * @hw: pointer to the HW structure 242 * @hdr: pointer to the host interface command header 243 * 244 * Writes the command header after does the checksum calculation. 245 */ 246 s32 247 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, 248 struct e1000_host_mng_command_header *hdr) 249 { 250 u16 i, length = sizeof (struct e1000_host_mng_command_header); 251 252 DEBUGFUNC("e1000_mng_write_cmd_header_generic"); 253 254 /* Write the whole command header structure with new checksum. */ 255 256 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); 257 258 length >>= 2; 259 /* Write the relevant command block into the ram area. */ 260 for (i = 0; i < length; i++) { 261 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, 262 *((u32 *) hdr + i)); 263 E1000_WRITE_FLUSH(hw); 264 } 265 266 return (E1000_SUCCESS); 267 } 268 269 /* 270 * e1000_mng_host_if_write_generic - Write to the manageability host interface 271 * @hw: pointer to the HW structure 272 * @buffer: pointer to the host interface buffer 273 * @length: size of the buffer 274 * @offset: location in the buffer to write to 275 * @sum: sum of the data (not checksum) 276 * 277 * This function writes the buffer content at the offset given on the host if. 278 * It also does alignment considerations to do the writes in most efficient 279 * way. Also fills up the sum of the buffer in *buffer parameter. 280 */ 281 s32 282 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, 283 u16 length, u16 offset, u8 *sum) 284 { 285 u8 *tmp; 286 u8 *bufptr = buffer; 287 u32 data = 0; 288 s32 ret_val = E1000_SUCCESS; 289 u16 remaining, i, j, prev_bytes; 290 291 DEBUGFUNC("e1000_mng_host_if_write_generic"); 292 293 /* sum = only sum of the data and it is not checksum */ 294 295 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { 296 ret_val = -E1000_ERR_PARAM; 297 goto out; 298 } 299 300 tmp = (u8 *)&data; 301 prev_bytes = offset & 0x3; 302 offset >>= 2; 303 304 if (prev_bytes) { 305 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); 306 for (j = prev_bytes; j < sizeof (u32); j++) { 307 *(tmp + j) = *bufptr++; 308 *sum += *(tmp + j); 309 } 310 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); 311 length -= j - prev_bytes; 312 offset++; 313 } 314 315 remaining = length & 0x3; 316 length -= remaining; 317 318 /* Calculate length in DWORDs */ 319 length >>= 2; 320 321 /* 322 * The device driver writes the relevant command block into the ram 323 * area. 324 */ 325 for (i = 0; i < length; i++) { 326 for (j = 0; j < sizeof (u32); j++) { 327 *(tmp + j) = *bufptr++; 328 *sum += *(tmp + j); 329 } 330 331 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 332 offset + i, data); 333 } 334 if (remaining) { 335 for (j = 0; j < sizeof (u32); j++) { 336 if (j < remaining) 337 *(tmp + j) = *bufptr++; 338 else 339 *(tmp + j) = 0; 340 341 *sum += *(tmp + j); 342 } 343 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 344 offset + i, data); 345 } 346 out: 347 return (ret_val); 348 } 349 350 /* 351 * e1000_enable_mng_pass_thru - Enable processing of ARP's 352 * @hw: pointer to the HW structure 353 * 354 * Verifies the hardware needs to allow ARPs to be processed by the host. 355 */ 356 bool 357 e1000_enable_mng_pass_thru(struct e1000_hw *hw) 358 { 359 u32 manc; 360 u32 fwsm, factps; 361 bool ret_val = FALSE; 362 363 DEBUGFUNC("e1000_enable_mng_pass_thru"); 364 365 if (!hw->mac.asf_firmware_present) 366 goto out; 367 368 manc = E1000_READ_REG(hw, E1000_MANC); 369 370 if (!(manc & E1000_MANC_RCV_TCO_EN) || 371 !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) 372 goto out; 373 374 if (hw->mac.arc_subsystem_valid) { 375 fwsm = E1000_READ_REG(hw, E1000_FWSM); 376 factps = E1000_READ_REG(hw, E1000_FACTPS); 377 378 if (!(factps & E1000_FACTPS_MNGCG) && 379 ((fwsm & E1000_FWSM_MODE_MASK) == 380 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { 381 ret_val = TRUE; 382 goto out; 383 } 384 } else { 385 if ((manc & E1000_MANC_SMBUS_EN) && 386 !(manc & E1000_MANC_ASF_EN)) { 387 ret_val = TRUE; 388 goto out; 389 } 390 } 391 392 out: 393 return (ret_val); 394 } 395