1fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/*******************************************************************************
2fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
3fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  Intel PRO/1000 Linux driver
4f5e261e626eb3fe07adf484aaad2ecfc757feba3Bruce Allan  Copyright(c) 1999 - 2012 Intel Corporation.
5fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
6fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  This program is free software; you can redistribute it and/or modify it
7fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  under the terms and conditions of the GNU General Public License,
8fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  version 2, as published by the Free Software Foundation.
9fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
10fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  This program is distributed in the hope it will be useful, but WITHOUT
11fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  more details.
14fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
15fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  You should have received a copy of the GNU General Public License along with
16fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  this program; if not, write to the Free Software Foundation, Inc.,
17fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
19fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  The full GNU General Public License is included in this distribution in
20fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  the file called "COPYING".
21fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
22fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  Contact Information:
23fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  Linux NICS <linux.nics@intel.com>
24fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
25fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
27fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan*******************************************************************************/
28fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
29fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan#include "e1000.h"
30fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
31fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allanenum e1000_mng_mode {
32fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	e1000_mng_mode_none = 0,
33fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	e1000_mng_mode_asf,
34fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	e1000_mng_mode_pt,
35fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	e1000_mng_mode_ipmi,
36fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	e1000_mng_mode_host_if_only
37fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan};
38fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
39fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan#define E1000_FACTPS_MNGCG		0x20000000
40fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
41fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/* Intel(R) Active Management Technology signature */
42fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan#define E1000_IAMT_SIGNATURE		0x544D4149
43fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
44fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/**
45fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  e1000_calculate_checksum - Calculate checksum for buffer
46fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @buffer: pointer to EEPROM
47fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @length: size of EEPROM to calculate a checksum for
48fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
49fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  Calculates the checksum for some buffer on a specified length.  The
50fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  checksum calculated is returned.
51fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan **/
52fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allanstatic u8 e1000_calculate_checksum(u8 *buffer, u32 length)
53fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan{
54fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 i;
55fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u8 sum = 0;
56fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
57fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (!buffer)
58fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		return 0;
59fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
60fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	for (i = 0; i < length; i++)
61fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		sum += buffer[i];
62fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
63fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	return (u8)(0 - sum);
64fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan}
65fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
66fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/**
67fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  e1000_mng_enable_host_if - Checks host interface is enabled
68fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @hw: pointer to the HW structure
69fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
70fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
71fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
72fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  This function checks whether the HOST IF is enabled for command operation
73fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  and also checks whether the previous command is completed.  It busy waits
74fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  in case of previous command is not completed.
75fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan **/
76fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allanstatic s32 e1000_mng_enable_host_if(struct e1000_hw *hw)
77fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan{
78fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 hicr;
79fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u8 i;
80fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
81668018d74762741c3fe5a54f0eea1bd65dcabd7eBruce Allan	if (!hw->mac.arc_subsystem_valid) {
82fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		e_dbg("ARC subsystem not valid.\n");
83fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		return -E1000_ERR_HOST_INTERFACE_COMMAND;
84fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
85fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
86fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Check that the host interface is enabled. */
87fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hicr = er32(HICR);
88fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if ((hicr & E1000_HICR_EN) == 0) {
89fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		e_dbg("E1000_HOST_EN bit disabled.\n");
90fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		return -E1000_ERR_HOST_INTERFACE_COMMAND;
91fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
92fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* check the previous command is completed */
93fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
94fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		hicr = er32(HICR);
95fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		if (!(hicr & E1000_HICR_C))
96fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan			break;
97fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		mdelay(1);
98fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
99fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
100fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
101fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		e_dbg("Previous command timeout failed .\n");
102fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		return -E1000_ERR_HOST_INTERFACE_COMMAND;
103fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
104fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
105fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	return 0;
106fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan}
107fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
108fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/**
10948768329efcf5e3970f54f6d15046f3e549101d8Bruce Allan *  e1000e_check_mng_mode_generic - Generic check management mode
110fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @hw: pointer to the HW structure
111fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
112fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  Reads the firmware semaphore register and returns true (>0) if
113fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  manageability is enabled, else false (0).
114fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan **/
115fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allanbool e1000e_check_mng_mode_generic(struct e1000_hw *hw)
116fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan{
117fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 fwsm = er32(FWSM);
118fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
119fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	return (fwsm & E1000_FWSM_MODE_MASK) ==
120fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	    (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
121fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan}
122fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
123fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/**
124fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx
125fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @hw: pointer to the HW structure
126fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
127fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  Enables packet filtering on transmit packets if manageability is enabled
128fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  and host interface is enabled.
129fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan **/
130fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allanbool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
131fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan{
132fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
133fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 *buffer = (u32 *)&hw->mng_cookie;
134fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 offset;
135fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	s32 ret_val, hdr_csum, csum;
136fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u8 i, len;
137fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
138fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hw->mac.tx_pkt_filtering = true;
139fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
140fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* No manageability, no filtering */
14148768329efcf5e3970f54f6d15046f3e549101d8Bruce Allan	if (!hw->mac.ops.check_mng_mode(hw)) {
142fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		hw->mac.tx_pkt_filtering = false;
1435015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan		return hw->mac.tx_pkt_filtering;
144fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
145fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
146fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/*
147fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 * If we can't read from the host interface for whatever
148fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 * reason, disable filtering.
149fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 */
150fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	ret_val = e1000_mng_enable_host_if(hw);
151fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (ret_val) {
152fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		hw->mac.tx_pkt_filtering = false;
1535015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan		return hw->mac.tx_pkt_filtering;
154fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
155fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
156fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Read in the header.  Length and offset are in dwords. */
157fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
158fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
159fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	for (i = 0; i < len; i++)
160fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		*(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF,
161fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan						     offset + i);
162fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hdr_csum = hdr->checksum;
163fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hdr->checksum = 0;
164fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	csum = e1000_calculate_checksum((u8 *)hdr,
165fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan					E1000_MNG_DHCP_COOKIE_LENGTH);
166fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/*
167fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 * If either the checksums or signature don't match, then
168fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 * the cookie area isn't considered valid, in which case we
169fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 * take the safe route of assuming Tx filtering is enabled.
170fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 */
171fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
172fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		hw->mac.tx_pkt_filtering = true;
1735015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan		return hw->mac.tx_pkt_filtering;
174fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
175fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
176fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Cookie area is valid, make the final check for filtering. */
1775015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan	if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
178fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		hw->mac.tx_pkt_filtering = false;
179fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
180fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	return hw->mac.tx_pkt_filtering;
181fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan}
182fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
183fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/**
184fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  e1000_mng_write_cmd_header - Writes manageability command header
185fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @hw: pointer to the HW structure
186fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @hdr: pointer to the host interface command header
187fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
188fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  Writes the command header after does the checksum calculation.
189fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan **/
190fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allanstatic s32 e1000_mng_write_cmd_header(struct e1000_hw *hw,
191fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan				      struct e1000_host_mng_command_header *hdr)
192fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan{
193fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u16 i, length = sizeof(struct e1000_host_mng_command_header);
194fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
195fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Write the whole command header structure with new checksum. */
196fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
197fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
198fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
199fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	length >>= 2;
200fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Write the relevant command block into the ram area. */
201fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	for (i = 0; i < length; i++) {
202fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, *((u32 *)hdr + i));
203fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		e1e_flush();
204fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
205fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
206fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	return 0;
207fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan}
208fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
209fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/**
210fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  e1000_mng_host_if_write - Write to the manageability host interface
211fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @hw: pointer to the HW structure
212fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @buffer: pointer to the host interface buffer
213fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @length: size of the buffer
214fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @offset: location in the buffer to write to
215fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @sum: sum of the data (not checksum)
216fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
217fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  This function writes the buffer content at the offset given on the host if.
218fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  It also does alignment considerations to do the writes in most efficient
219fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  way.  Also fills up the sum of the buffer in *buffer parameter.
220fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan **/
221fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allanstatic s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
222fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan				   u16 length, u16 offset, u8 *sum)
223fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan{
224fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u8 *tmp;
225fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u8 *bufptr = buffer;
226fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 data = 0;
227fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u16 remaining, i, j, prev_bytes;
228fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
229fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* sum = only sum of the data and it is not checksum */
230fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
231fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
232fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		return -E1000_ERR_PARAM;
233fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
234fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	tmp = (u8 *)&data;
235fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	prev_bytes = offset & 0x3;
236fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	offset >>= 2;
237fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
238fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (prev_bytes) {
239fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset);
240fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		for (j = prev_bytes; j < sizeof(u32); j++) {
241fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan			*(tmp + j) = *bufptr++;
242fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan			*sum += *(tmp + j);
243fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		}
244fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data);
245fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		length -= j - prev_bytes;
246fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		offset++;
247fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
248fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
249fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	remaining = length & 0x3;
250fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	length -= remaining;
251fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
252fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Calculate length in DWORDs */
253fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	length >>= 2;
254fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
255fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/*
256fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 * The device driver writes the relevant command block into the
257fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 * ram area.
258fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	 */
259fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	for (i = 0; i < length; i++) {
260fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		for (j = 0; j < sizeof(u32); j++) {
261fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan			*(tmp + j) = *bufptr++;
262fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan			*sum += *(tmp + j);
263fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		}
264fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
265fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
266fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
267fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (remaining) {
268fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		for (j = 0; j < sizeof(u32); j++) {
269fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan			if (j < remaining)
270fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan				*(tmp + j) = *bufptr++;
271fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan			else
272fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan				*(tmp + j) = 0;
273fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
274fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan			*sum += *(tmp + j);
275fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		}
276fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data);
277fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
278fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
279fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	return 0;
280fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan}
281fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
282fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/**
283fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  e1000e_mng_write_dhcp_info - Writes DHCP info to host interface
284fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @hw: pointer to the HW structure
285fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @buffer: pointer to the host interface
286fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @length: size of the buffer
287fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
288fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  Writes the DHCP information to the host interface.
289fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan **/
290fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allans32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length)
291fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan{
292fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	struct e1000_host_mng_command_header hdr;
293fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	s32 ret_val;
294fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 hicr;
295fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
296fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
297fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hdr.command_length = length;
298fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hdr.reserved1 = 0;
299fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hdr.reserved2 = 0;
300fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hdr.checksum = 0;
301fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
302fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Enable the host interface */
303fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	ret_val = e1000_mng_enable_host_if(hw);
304fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (ret_val)
305fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		return ret_val;
306fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
307fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Populate the host interface with the contents of "buffer". */
308fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	ret_val = e1000_mng_host_if_write(hw, buffer, length,
309fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan					  sizeof(hdr), &(hdr.checksum));
310fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (ret_val)
311fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		return ret_val;
312fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
313fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Write the manageability command header */
314fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	ret_val = e1000_mng_write_cmd_header(hw, &hdr);
315fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (ret_val)
316fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		return ret_val;
317fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
318fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	/* Tell the ARC a new command is pending. */
319fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	hicr = er32(HICR);
320fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	ew32(HICR, hicr | E1000_HICR_C);
321fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
322fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	return 0;
323fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan}
324fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
325fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan/**
326fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  e1000e_enable_mng_pass_thru - Check if management passthrough is needed
327fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  @hw: pointer to the HW structure
328fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *
329fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  Verifies the hardware needs to leave interface enabled so that frames can
330fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan *  be directed to and from the management interface.
331fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan **/
332fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allanbool e1000e_enable_mng_pass_thru(struct e1000_hw *hw)
333fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan{
334fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 manc;
335fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	u32 fwsm, factps;
336fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
337fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	manc = er32(MANC);
338fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
339fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (!(manc & E1000_MANC_RCV_TCO_EN))
3405015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan		return false;
341fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
342fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	if (hw->mac.has_fwsm) {
343fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		fwsm = er32(FWSM);
344fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		factps = er32(FACTPS);
345fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
346fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		if (!(factps & E1000_FACTPS_MNGCG) &&
347fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		    ((fwsm & E1000_FWSM_MODE_MASK) ==
3485015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan		     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
3495015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan			return true;
350fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	} else if ((hw->mac.type == e1000_82574) ||
351fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		   (hw->mac.type == e1000_82583)) {
352fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		u16 data;
353fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
354fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		factps = er32(FACTPS);
355fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
356fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
357fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		if (!(factps & E1000_FACTPS_MNGCG) &&
358fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		    ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
3595015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan		     (e1000_mng_mode_pt << 13)))
3605015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan			return true;
361fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	} else if ((manc & E1000_MANC_SMBUS_EN) &&
362fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan		   !(manc & E1000_MANC_ASF_EN)) {
3635015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan		return true;
364fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan	}
365fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan
3665015e53a4cf0c88977120faede7eb02b0459d90eBruce Allan	return false;
367fe2ddfb510f9d305a6654c7538c5c8faf326a16cBruce Allan}
368