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