1 /* 2 * CDDL HEADER START 3 * 4 * Copyright(c) 2007-2008 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 2008 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms of the CDDL. 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include "igb_api.h" 32 #include "igb_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 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 operaton 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 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 bool 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 bool 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 bool 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 151 * reason, 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, 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 172 * the cookie area isn't considered valid, in which case we 173 * take the safe route 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 = e1000_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 = e1000_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 = e1000_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 321 * ram 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 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 bool 356 e1000_enable_mng_pass_thru(struct e1000_hw *hw) 357 { 358 u32 manc; 359 u32 fwsm, factps; 360 bool 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