xref: /dragonfly/sys/dev/netif/ig_hal/e1000_manage.c (revision 650094e1)
1 /******************************************************************************
2 
3   Copyright (c) 2001-2009, Intel Corporation
4   All rights reserved.
5 
6   Redistribution and use in source and binary forms, with or without
7   modification, are permitted provided that the following conditions are met:
8 
9    1. Redistributions of source code must retain the above copyright notice,
10       this list of conditions and the following disclaimer.
11 
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.
15 
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.
19 
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.
31 
32 ******************************************************************************/
33 /*$FreeBSD: $*/
34 
35 #include "e1000_api.h"
36 
37 static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
38 
39 /**
40  *  e1000_calculate_checksum - Calculate checksum for buffer
41  *  @buffer: pointer to EEPROM
42  *  @length: size of EEPROM to calculate a checksum for
43  *
44  *  Calculates the checksum for some buffer on a specified length.  The
45  *  checksum calculated is returned.
46  **/
47 static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
48 {
49 	u32 i;
50 	u8  sum = 0;
51 
52 	DEBUGFUNC("e1000_calculate_checksum");
53 
54 	if (!buffer)
55 		return 0;
56 
57 	for (i = 0; i < length; i++)
58 		sum += buffer[i];
59 
60 	return (u8) (0 - sum);
61 }
62 
63 /**
64  *  e1000_mng_enable_host_if_generic - Checks host interface is enabled
65  *  @hw: pointer to the HW structure
66  *
67  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
68  *
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.
72  **/
73 s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
74 {
75 	u32 hicr;
76 	s32 ret_val = E1000_SUCCESS;
77 	u8 i;
78 
79 	DEBUGFUNC("e1000_mng_enable_host_if_generic");
80 
81 	if (!(hw->mac.arc_subsystem_valid)) {
82 		DEBUGOUT("ARC subsystem not valid.\n");
83 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
84 		goto out;
85 	}
86 
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;
92 		goto out;
93 	}
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))
98 			break;
99 		msec_delay_irq(1);
100 	}
101 
102 	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
103 		DEBUGOUT("Previous command timeout failed .\n");
104 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
105 		goto out;
106 	}
107 
108 out:
109 	return ret_val;
110 }
111 
112 /**
113  *  e1000_check_mng_mode_generic - Generic check management mode
114  *  @hw: pointer to the HW structure
115  *
116  *  Reads the firmware semaphore register and returns TRUE (>0) if
117  *  manageability is enabled, else FALSE (0).
118  **/
119 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
120 {
121 	u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
122 
123 	DEBUGFUNC("e1000_check_mng_mode_generic");
124 
125 
126 	return (fwsm & E1000_FWSM_MODE_MASK) ==
127 	        (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
128 }
129 
130 /**
131  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
132  *  @hw: pointer to the HW structure
133  *
134  *  Enables packet filtering on transmit packets if manageability is enabled
135  *  and host interface is enabled.
136  **/
137 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
138 {
139 	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
140 	u32 *buffer = (u32 *)&hw->mng_cookie;
141 	u32 offset;
142 	s32 ret_val, hdr_csum, csum;
143 	u8 i, len;
144 
145 	DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
146 
147 	hw->mac.tx_pkt_filtering = TRUE;
148 
149 	/* No manageability, no filtering */
150 	if (!hw->mac.ops.check_mng_mode(hw)) {
151 		hw->mac.tx_pkt_filtering = FALSE;
152 		goto out;
153 	}
154 
155 	/*
156 	 * If we can't read from the host interface for whatever
157 	 * reason, disable filtering.
158 	 */
159 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
160 	if (ret_val != E1000_SUCCESS) {
161 		hw->mac.tx_pkt_filtering = FALSE;
162 		goto out;
163 	}
164 
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,
170 		                                           offset + i);
171 	hdr_csum = hdr->checksum;
172 	hdr->checksum = 0;
173 	csum = e1000_calculate_checksum((u8 *)hdr,
174 	                                E1000_MNG_DHCP_COOKIE_LENGTH);
175 	/*
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.
179 	 */
180 	if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
181 		hw->mac.tx_pkt_filtering = TRUE;
182 		goto out;
183 	}
184 
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;
188 		goto out;
189 	}
190 
191 out:
192 	return hw->mac.tx_pkt_filtering;
193 }
194 
195 /**
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
200  *
201  *  Writes the DHCP information to the host interface.
202  **/
203 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
204                                       u16 length)
205 {
206 	struct e1000_host_mng_command_header hdr;
207 	s32 ret_val;
208 	u32 hicr;
209 
210 	DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
211 
212 	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
213 	hdr.command_length = length;
214 	hdr.reserved1 = 0;
215 	hdr.reserved2 = 0;
216 	hdr.checksum = 0;
217 
218 	/* Enable the host interface */
219 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
220 	if (ret_val)
221 		goto out;
222 
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));
226 	if (ret_val)
227 		goto out;
228 
229 	/* Write the manageability command header */
230 	ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
231 	if (ret_val)
232 		goto out;
233 
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);
237 
238 out:
239 	return ret_val;
240 }
241 
242 /**
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
246  *
247  *  Writes the command header after does the checksum calculation.
248  **/
249 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
250                                     struct e1000_host_mng_command_header *hdr)
251 {
252 	u16 i, length = sizeof(struct e1000_host_mng_command_header);
253 
254 	DEBUGFUNC("e1000_mng_write_cmd_header_generic");
255 
256 	/* Write the whole command header structure with new checksum. */
257 
258 	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
259 
260 	length >>= 2;
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,
264 		                            *((u32 *) hdr + i));
265 		E1000_WRITE_FLUSH(hw);
266 	}
267 
268 	return E1000_SUCCESS;
269 }
270 
271 /**
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)
278  *
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.
282  **/
283 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
284                                     u16 length, u16 offset, u8 *sum)
285 {
286 	u8 *tmp;
287 	u8 *bufptr = buffer;
288 	u32 data = 0;
289 	s32 ret_val = E1000_SUCCESS;
290 	u16 remaining, i, j, prev_bytes;
291 
292 	DEBUGFUNC("e1000_mng_host_if_write_generic");
293 
294 	/* sum = only sum of the data and it is not checksum */
295 
296 	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
297 		ret_val = -E1000_ERR_PARAM;
298 		goto out;
299 	}
300 
301 	tmp = (u8 *)&data;
302 	prev_bytes = offset & 0x3;
303 	offset >>= 2;
304 
305 	if (prev_bytes) {
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++;
309 			*sum += *(tmp + j);
310 		}
311 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
312 		length -= j - prev_bytes;
313 		offset++;
314 	}
315 
316 	remaining = length & 0x3;
317 	length -= remaining;
318 
319 	/* Calculate length in DWORDs */
320 	length >>= 2;
321 
322 	/*
323 	 * The device driver writes the relevant command block into the
324 	 * ram area.
325 	 */
326 	for (i = 0; i < length; i++) {
327 		for (j = 0; j < sizeof(u32); j++) {
328 			*(tmp + j) = *bufptr++;
329 			*sum += *(tmp + j);
330 		}
331 
332 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
333 		                            data);
334 	}
335 	if (remaining) {
336 		for (j = 0; j < sizeof(u32); j++) {
337 			if (j < remaining)
338 				*(tmp + j) = *bufptr++;
339 			else
340 				*(tmp + j) = 0;
341 
342 			*sum += *(tmp + j);
343 		}
344 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
345 	}
346 
347 out:
348 	return ret_val;
349 }
350 
351 /**
352  *  e1000_enable_mng_pass_thru - Check if management passthrough is needed
353  *  @hw: pointer to the HW structure
354  *
355  *  Verifies the hardware needs to leave interface enabled so that frames can
356  *  be directed to and from the management interface.
357  **/
358 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
359 {
360 	u32 manc;
361 	u32 fwsm, factps;
362 	bool ret_val = FALSE;
363 
364 	DEBUGFUNC("e1000_enable_mng_pass_thru");
365 
366 	if (!hw->mac.asf_firmware_present)
367 		goto out;
368 
369 	manc = E1000_READ_REG(hw, E1000_MANC);
370 
371 	if (!(manc & E1000_MANC_RCV_TCO_EN))
372 		goto out;
373 
374 	if (hw->mac.has_fwsm) {
375 		fwsm = E1000_READ_REG(hw, E1000_FWSM);
376 		factps = E1000_READ_REG(hw, E1000_FACTPS);
377 
378 		if (!(factps & E1000_FACTPS_MNGCG) &&
379 		    ((fwsm & E1000_FWSM_MODE_MASK) ==
380 		     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
381 			ret_val = TRUE;
382 			goto out;
383 		}
384 	} else if ((hw->mac.type == e1000_82574) ||
385 		   (hw->mac.type == e1000_82583)) {
386 		u16 data;
387 
388 		factps = E1000_READ_REG(hw, E1000_FACTPS);
389 		e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
390 
391 		if (!(factps & E1000_FACTPS_MNGCG) &&
392 		    ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
393 		     (e1000_mng_mode_pt << 13))) {
394 			ret_val = TRUE;
395 			goto out;
396 		}
397 	} else if ((manc & E1000_MANC_SMBUS_EN) &&
398 		    !(manc & E1000_MANC_ASF_EN)) {
399 			ret_val = TRUE;
400 			goto out;
401 	}
402 
403 out:
404 	return ret_val;
405 }
406 
407