1 /******************************************************************************
3 Copyright (c) 2001-2010, Intel Corporation
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
32 ******************************************************************************/
35 #include "e1000_api.h"
37 static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
40 * e1000_calculate_checksum - Calculate checksum for buffer
41 * @buffer: pointer to EEPROM
42 * @length: size of EEPROM to calculate a checksum for
44 * Calculates the checksum for some buffer on a specified length. The
45 * checksum calculated is returned.
47 static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
52 DEBUGFUNC("e1000_calculate_checksum");
57 for (i = 0; i < length; i++)
60 return (u8) (0 - sum);
64 * e1000_mng_enable_host_if_generic - Checks host interface is enabled
65 * @hw: pointer to the HW structure
67 * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
69 * This function checks whether the HOST IF is enabled for command operation
70 * and also checks whether the previous command is completed. It busy waits
71 * in case of previous command is not completed.
73 s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
76 s32 ret_val = E1000_SUCCESS;
79 DEBUGFUNC("e1000_mng_enable_host_if_generic");
81 if (!(hw->mac.arc_subsystem_valid)) {
82 DEBUGOUT("ARC subsystem not valid.\n");
83 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
87 /* Check that the host interface is enabled. */
88 hicr = E1000_READ_REG(hw, E1000_HICR);
89 if ((hicr & E1000_HICR_EN) == 0) {
90 DEBUGOUT("E1000_HOST_EN bit disabled.\n");
91 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
94 /* check the previous command is completed */
95 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
96 hicr = E1000_READ_REG(hw, E1000_HICR);
97 if (!(hicr & E1000_HICR_C))
102 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
103 DEBUGOUT("Previous command timeout failed .\n");
104 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
113 * e1000_check_mng_mode_generic - Generic check management mode
114 * @hw: pointer to the HW structure
116 * Reads the firmware semaphore register and returns TRUE (>0) if
117 * manageability is enabled, else FALSE (0).
119 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
121 u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
123 DEBUGFUNC("e1000_check_mng_mode_generic");
126 return (fwsm & E1000_FWSM_MODE_MASK) ==
127 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
131 * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
132 * @hw: pointer to the HW structure
134 * Enables packet filtering on transmit packets if manageability is enabled
135 * and host interface is enabled.
137 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
139 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
140 u32 *buffer = (u32 *)&hw->mng_cookie;
142 s32 ret_val, hdr_csum, csum;
145 DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
147 hw->mac.tx_pkt_filtering = TRUE;
149 /* No manageability, no filtering */
150 if (!hw->mac.ops.check_mng_mode(hw)) {
151 hw->mac.tx_pkt_filtering = FALSE;
156 * If we can't read from the host interface for whatever
157 * reason, disable filtering.
159 ret_val = hw->mac.ops.mng_enable_host_if(hw);
160 if (ret_val != E1000_SUCCESS) {
161 hw->mac.tx_pkt_filtering = FALSE;
165 /* Read in the header. Length and offset are in dwords. */
166 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
167 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
168 for (i = 0; i < len; i++)
169 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
171 hdr_csum = hdr->checksum;
173 csum = e1000_calculate_checksum((u8 *)hdr,
174 E1000_MNG_DHCP_COOKIE_LENGTH);
176 * If either the checksums or signature don't match, then
177 * the cookie area isn't considered valid, in which case we
178 * take the safe route of assuming Tx filtering is enabled.
180 if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
181 hw->mac.tx_pkt_filtering = TRUE;
185 /* Cookie area is valid, make the final check for filtering. */
186 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
187 hw->mac.tx_pkt_filtering = FALSE;
192 return hw->mac.tx_pkt_filtering;
196 * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
197 * @hw: pointer to the HW structure
198 * @buffer: pointer to the host interface
199 * @length: size of the buffer
201 * Writes the DHCP information to the host interface.
203 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
206 struct e1000_host_mng_command_header hdr;
210 DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
212 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
213 hdr.command_length = length;
218 /* Enable the host interface */
219 ret_val = hw->mac.ops.mng_enable_host_if(hw);
223 /* Populate the host interface with the contents of "buffer". */
224 ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
225 sizeof(hdr), &(hdr.checksum));
229 /* Write the manageability command header */
230 ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
234 /* Tell the ARC a new command is pending. */
235 hicr = E1000_READ_REG(hw, E1000_HICR);
236 E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
243 * e1000_mng_write_cmd_header_generic - Writes manageability command header
244 * @hw: pointer to the HW structure
245 * @hdr: pointer to the host interface command header
247 * Writes the command header after does the checksum calculation.
249 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
250 struct e1000_host_mng_command_header *hdr)
252 u16 i, length = sizeof(struct e1000_host_mng_command_header);
254 DEBUGFUNC("e1000_mng_write_cmd_header_generic");
256 /* Write the whole command header structure with new checksum. */
258 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
261 /* Write the relevant command block into the ram area. */
262 for (i = 0; i < length; i++) {
263 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
265 E1000_WRITE_FLUSH(hw);
268 return E1000_SUCCESS;
272 * e1000_mng_host_if_write_generic - Write to the manageability host interface
273 * @hw: pointer to the HW structure
274 * @buffer: pointer to the host interface buffer
275 * @length: size of the buffer
276 * @offset: location in the buffer to write to
277 * @sum: sum of the data (not checksum)
279 * This function writes the buffer content at the offset given on the host if.
280 * It also does alignment considerations to do the writes in most efficient
281 * way. Also fills up the sum of the buffer in *buffer parameter.
283 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
284 u16 length, u16 offset, u8 *sum)
289 s32 ret_val = E1000_SUCCESS;
290 u16 remaining, i, j, prev_bytes;
292 DEBUGFUNC("e1000_mng_host_if_write_generic");
294 /* sum = only sum of the data and it is not checksum */
296 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
297 ret_val = -E1000_ERR_PARAM;
302 prev_bytes = offset & 0x3;
306 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
307 for (j = prev_bytes; j < sizeof(u32); j++) {
308 *(tmp + j) = *bufptr++;
311 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
312 length -= j - prev_bytes;
316 remaining = length & 0x3;
319 /* Calculate length in DWORDs */
323 * The device driver writes the relevant command block into the
326 for (i = 0; i < length; i++) {
327 for (j = 0; j < sizeof(u32); j++) {
328 *(tmp + j) = *bufptr++;
332 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
336 for (j = 0; j < sizeof(u32); j++) {
338 *(tmp + j) = *bufptr++;
344 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
352 * e1000_enable_mng_pass_thru - Check if management passthrough is needed
353 * @hw: pointer to the HW structure
355 * Verifies the hardware needs to leave interface enabled so that frames can
356 * be directed to and from the management interface.
358 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
362 bool ret_val = FALSE;
364 DEBUGFUNC("e1000_enable_mng_pass_thru");
366 if (!hw->mac.asf_firmware_present)
369 manc = E1000_READ_REG(hw, E1000_MANC);
371 if (!(manc & E1000_MANC_RCV_TCO_EN))
374 if (hw->mac.has_fwsm) {
375 fwsm = E1000_READ_REG(hw, E1000_FWSM);
376 factps = E1000_READ_REG(hw, E1000_FACTPS);
378 if (!(factps & E1000_FACTPS_MNGCG) &&
379 ((fwsm & E1000_FWSM_MODE_MASK) ==
380 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
384 } else if ((hw->mac.type == e1000_82574) ||
385 (hw->mac.type == e1000_82583)) {
388 factps = E1000_READ_REG(hw, E1000_FACTPS);
389 e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
391 if (!(factps & E1000_FACTPS_MNGCG) &&
392 ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
393 (e1000_mng_mode_pt << 13))) {
397 } else if ((manc & E1000_MANC_SMBUS_EN) &&
398 !(manc & E1000_MANC_ASF_EN)) {