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 - 2007 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 2007 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: HSD_2343720b_DragonLake3 v2007-06-14_HSD_2343720b_DragonLake3 30 */ 31 #include "e1000_api.h" 32 #include "e1000_manage.h" 33 34 static u8 e1000_calculate_checksum(u8 *buffer, u32 length); 35 36 /* 37 * e1000_calculate_checksum - Calculate checksum for buffer 38 * @buffer: pointer to EEPROM 39 * @length: size of EEPROM to calculate a checksum for 40 * 41 * Calculates the checksum for some buffer on a specified length. The 42 * checksum calculated is returned. 43 */ 44 static u8 45 e1000_calculate_checksum(u8 *buffer, u32 length) 46 { 47 u32 i; 48 u8 sum = 0; 49 50 DEBUGFUNC("e1000_calculate_checksum"); 51 52 if (!buffer) 53 return (0); 54 55 for (i = 0; i < length; i++) 56 sum += buffer[i]; 57 58 return (u8)(0 - sum); 59 } 60 61 /* 62 * e1000_mng_enable_host_if_generic - Checks host interface is enabled 63 * @hw: pointer to the HW structure 64 * 65 * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND 66 * 67 * This function checks whether the HOST IF is enabled for command operaton 68 * and also checks whether the previous command is completed. It busy waits 69 * in case of previous command is not completed. 70 */ 71 s32 72 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) 73 { 74 u32 hicr; 75 s32 ret_val = E1000_SUCCESS; 76 u8 i; 77 78 DEBUGFUNC("e1000_mng_enable_host_if_generic"); 79 80 /* Check that the host interface is enabled. */ 81 hicr = E1000_READ_REG(hw, E1000_HICR); 82 if ((hicr & E1000_HICR_EN) == 0) { 83 DEBUGOUT("E1000_HOST_EN bit disabled.\n"); 84 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 85 goto out; 86 } 87 /* check the previous command is completed */ 88 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { 89 hicr = E1000_READ_REG(hw, E1000_HICR); 90 if (!(hicr & E1000_HICR_C)) 91 break; 92 msec_delay_irq(1); 93 } 94 95 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 96 DEBUGOUT("Previous command timeout failed .\n"); 97 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND; 98 goto out; 99 } 100 out: 101 return (ret_val); 102 } 103 104 /* 105 * e1000_check_mng_mode_generic - Generic check managament mode 106 * @hw: pointer to the HW structure 107 * 108 * Reads the firmware semaphore register and returns true (>0) if 109 * manageability is enabled, else false (0). 110 */ 111 boolean_t 112 e1000_check_mng_mode_generic(struct e1000_hw *hw) 113 { 114 u32 fwsm; 115 116 DEBUGFUNC("e1000_check_mng_mode_generic"); 117 118 fwsm = E1000_READ_REG(hw, E1000_FWSM); 119 120 return ((fwsm & E1000_FWSM_MODE_MASK) == 121 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); 122 } 123 124 /* 125 * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX 126 * @hw: pointer to the HW structure 127 * 128 * Enables packet filtering on transmit packets if manageability is enabled 129 * and host interface is enabled. 130 */ 131 boolean_t 132 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 boolean_t tx_filter = TRUE; 140 141 DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); 142 143 /* No manageability, no filtering */ 144 if (!e1000_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 reason, 151 * disable filtering. 152 */ 153 ret_val = e1000_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, 164 E1000_HOST_IF, 165 offset + i); 166 } 167 hdr_csum = hdr->checksum; 168 hdr->checksum = 0; 169 csum = e1000_calculate_checksum((u8 *)hdr, 170 E1000_MNG_DHCP_COOKIE_LENGTH); 171 /* 172 * If either the checksums or signature don't match, then the cookie 173 * area isn't considered valid, in which case we take the safe route 174 * of assuming Tx filtering is enabled. 175 */ 176 if (hdr_csum != csum) 177 goto out; 178 if (hdr->signature != E1000_IAMT_SIGNATURE) 179 goto out; 180 181 /* Cookie area is valid, make the final check for filtering. */ 182 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) 183 tx_filter = FALSE; 184 185 out: 186 hw->mac.tx_pkt_filtering = tx_filter; 187 return (tx_filter); 188 } 189 190 /* 191 * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface 192 * @hw: pointer to the HW structure 193 * @buffer: pointer to the host interface 194 * @length: size of the buffer 195 * 196 * Writes the DHCP information to the host interface. 197 */ 198 s32 199 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, 200 u16 length) 201 { 202 struct e1000_host_mng_command_header hdr; 203 s32 ret_val; 204 u32 hicr; 205 206 DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); 207 208 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; 209 hdr.command_length = length; 210 hdr.reserved1 = 0; 211 hdr.reserved2 = 0; 212 hdr.checksum = 0; 213 214 /* Enable the host interface */ 215 ret_val = e1000_mng_enable_host_if(hw); 216 if (ret_val) 217 goto out; 218 219 /* Populate the host interface with the contents of "buffer". */ 220 ret_val = e1000_mng_host_if_write(hw, buffer, length, 221 sizeof (hdr), &(hdr.checksum)); 222 if (ret_val) 223 goto out; 224 225 /* Write the manageability command header */ 226 ret_val = e1000_mng_write_cmd_header(hw, &hdr); 227 if (ret_val) 228 goto out; 229 230 /* Tell the ARC a new command is pending. */ 231 hicr = E1000_READ_REG(hw, E1000_HICR); 232 E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 233 234 out: 235 return (ret_val); 236 } 237 238 /* 239 * e1000_mng_write_cmd_header_generic - Writes manageability command header 240 * @hw: pointer to the HW structure 241 * @hdr: pointer to the host interface command header 242 * 243 * Writes the command header after does the checksum calculation. 244 */ 245 s32 246 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, 247 struct e1000_host_mng_command_header *hdr) 248 { 249 u16 i, length = sizeof (struct e1000_host_mng_command_header); 250 251 DEBUGFUNC("e1000_mng_write_cmd_header_generic"); 252 253 /* Write the whole command header structure with new checksum. */ 254 255 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); 256 257 length >>= 2; 258 /* Write the relevant command block into the ram area. */ 259 for (i = 0; i < length; i++) { 260 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, 261 *((u32 *) hdr + i)); 262 E1000_WRITE_FLUSH(hw); 263 } 264 265 return (E1000_SUCCESS); 266 } 267 268 /* 269 * e1000_mng_host_if_write_generic - Writes to the manageability host interface 270 * @hw: pointer to the HW structure 271 * @buffer: pointer to the host interface buffer 272 * @length: size of the buffer 273 * @offset: location in the buffer to write to 274 * @sum: sum of the data (not checksum) 275 * 276 * This function writes the buffer content at the offset given on the host if. 277 * It also does alignment considerations to do the writes in most efficient 278 * way. Also fills up the sum of the buffer in *buffer parameter. 279 */ 280 s32 281 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, 282 u16 length, u16 offset, u8 *sum) 283 { 284 u8 *tmp; 285 u8 *bufptr = buffer; 286 u32 data = 0; 287 s32 ret_val = E1000_SUCCESS; 288 u16 remaining, i, j, prev_bytes; 289 290 DEBUGFUNC("e1000_mng_host_if_write_generic"); 291 292 /* sum = only sum of the data and it is not checksum */ 293 294 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) { 295 ret_val = -E1000_ERR_PARAM; 296 goto out; 297 } 298 299 tmp = (u8 *)&data; 300 prev_bytes = offset & 0x3; 301 offset >>= 2; 302 303 if (prev_bytes) { 304 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); 305 for (j = prev_bytes; j < sizeof (u32); j++) { 306 *(tmp + j) = *bufptr++; 307 *sum += *(tmp + j); 308 } 309 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); 310 length -= j - prev_bytes; 311 offset++; 312 } 313 314 remaining = length & 0x3; 315 length -= remaining; 316 317 /* Calculate length in DWORDs */ 318 length >>= 2; 319 320 /* 321 * The device driver writes the relevant command block into the ram 322 * area. 323 */ 324 for (i = 0; i < length; i++) { 325 for (j = 0; j < sizeof (u32); j++) { 326 *(tmp + j) = *bufptr++; 327 *sum += *(tmp + j); 328 } 329 330 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 331 offset + i, data); 332 } 333 if (remaining) { 334 for (j = 0; j < sizeof (u32); j++) { 335 if (j < remaining) 336 *(tmp + j) = *bufptr++; 337 else 338 *(tmp + j) = 0; 339 340 *sum += *(tmp + j); 341 } 342 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 343 offset + i, data); 344 } 345 out: 346 return (ret_val); 347 } 348 349 /* 350 * e1000_enable_mng_pass_thru - Enable processing of ARP's 351 * @hw: pointer to the HW structure 352 * 353 * Verifies the hardware needs to allow ARPs to be processed by the host. 354 */ 355 boolean_t 356 e1000_enable_mng_pass_thru(struct e1000_hw *hw) 357 { 358 u32 manc; 359 u32 fwsm, factps; 360 boolean_t ret_val = FALSE; 361 362 DEBUGFUNC("e1000_enable_mng_pass_thru"); 363 364 if (!hw->mac.asf_firmware_present) 365 goto out; 366 367 manc = E1000_READ_REG(hw, E1000_MANC); 368 369 if (!(manc & E1000_MANC_RCV_TCO_EN) || 370 !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) 371 goto out; 372 373 if (hw->mac.arc_subsystem_valid) { 374 fwsm = E1000_READ_REG(hw, E1000_FWSM); 375 factps = E1000_READ_REG(hw, E1000_FACTPS); 376 377 if (!(factps & E1000_FACTPS_MNGCG) && 378 ((fwsm & E1000_FWSM_MODE_MASK) == 379 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) { 380 ret_val = TRUE; 381 goto out; 382 } 383 } else { 384 if ((manc & E1000_MANC_SMBUS_EN) && 385 !(manc & E1000_MANC_ASF_EN)) { 386 ret_val = TRUE; 387 goto out; 388 } 389 } 390 391 out: 392 return (ret_val); 393 } 394