xref: /freebsd/sys/dev/e1000/e1000_manage.c (revision 9a14aa017b21c292740c00ee098195cd46642730)
1 /******************************************************************************
2 
3   Copyright (c) 2001-2010, 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 /**
38  *  e1000_calculate_checksum - Calculate checksum for buffer
39  *  @buffer: pointer to EEPROM
40  *  @length: size of EEPROM to calculate a checksum for
41  *
42  *  Calculates the checksum for some buffer on a specified length.  The
43  *  checksum calculated is returned.
44  **/
45 u8 e1000_calculate_checksum(u8 *buffer, u32 length)
46 {
47 	u32 i;
48 	u8 sum = 0;
49 
50 	DEBUGFUNC("e1000_calculate_checksum");
51 
52 	if (!buffer)
53 		return 0;
54 
55 	for (i = 0; i < length; i++)
56 		sum += buffer[i];
57 
58 	return (u8) (0 - sum);
59 }
60 
61 /**
62  *  e1000_mng_enable_host_if_generic - Checks host interface is enabled
63  *  @hw: pointer to the HW structure
64  *
65  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
66  *
67  *  This function checks whether the HOST IF is enabled for command operation
68  *  and also checks whether the previous command is completed.  It busy waits
69  *  in case of previous command is not completed.
70  **/
71 s32 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 	if (!(hw->mac.arc_subsystem_valid)) {
80 		DEBUGOUT("ARC subsystem not valid.\n");
81 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
82 		goto out;
83 	}
84 
85 	/* Check that the host interface is enabled. */
86 	hicr = E1000_READ_REG(hw, E1000_HICR);
87 	if ((hicr & E1000_HICR_EN) == 0) {
88 		DEBUGOUT("E1000_HOST_EN bit disabled.\n");
89 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
90 		goto out;
91 	}
92 	/* check the previous command is completed */
93 	for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
94 		hicr = E1000_READ_REG(hw, E1000_HICR);
95 		if (!(hicr & E1000_HICR_C))
96 			break;
97 		msec_delay_irq(1);
98 	}
99 
100 	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
101 		DEBUGOUT("Previous command timeout failed .\n");
102 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
103 		goto out;
104 	}
105 
106 out:
107 	return ret_val;
108 }
109 
110 /**
111  *  e1000_check_mng_mode_generic - Generic check management mode
112  *  @hw: pointer to the HW structure
113  *
114  *  Reads the firmware semaphore register and returns TRUE (>0) if
115  *  manageability is enabled, else FALSE (0).
116  **/
117 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
118 {
119 	u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
120 
121 	DEBUGFUNC("e1000_check_mng_mode_generic");
122 
123 
124 	return (fwsm & E1000_FWSM_MODE_MASK) ==
125 	        (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
126 }
127 
128 /**
129  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
130  *  @hw: pointer to the HW structure
131  *
132  *  Enables packet filtering on transmit packets if manageability is enabled
133  *  and host interface is enabled.
134  **/
135 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
136 {
137 	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
138 	u32 *buffer = (u32 *)&hw->mng_cookie;
139 	u32 offset;
140 	s32 ret_val, hdr_csum, csum;
141 	u8 i, len;
142 
143 	DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
144 
145 	hw->mac.tx_pkt_filtering = TRUE;
146 
147 	/* No manageability, no filtering */
148 	if (!hw->mac.ops.check_mng_mode(hw)) {
149 		hw->mac.tx_pkt_filtering = FALSE;
150 		goto out;
151 	}
152 
153 	/*
154 	 * If we can't read from the host interface for whatever
155 	 * reason, disable filtering.
156 	 */
157 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
158 	if (ret_val != E1000_SUCCESS) {
159 		hw->mac.tx_pkt_filtering = FALSE;
160 		goto out;
161 	}
162 
163 	/* Read in the header.  Length and offset are in dwords. */
164 	len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
165 	offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
166 	for (i = 0; i < len; i++)
167 		*(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
168 		                                           offset + i);
169 	hdr_csum = hdr->checksum;
170 	hdr->checksum = 0;
171 	csum = e1000_calculate_checksum((u8 *)hdr,
172 	                                E1000_MNG_DHCP_COOKIE_LENGTH);
173 	/*
174 	 * If either the checksums or signature don't match, then
175 	 * the cookie area isn't considered valid, in which case we
176 	 * take the safe route of assuming Tx filtering is enabled.
177 	 */
178 	if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
179 		hw->mac.tx_pkt_filtering = TRUE;
180 		goto out;
181 	}
182 
183 	/* Cookie area is valid, make the final check for filtering. */
184 	if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
185 		hw->mac.tx_pkt_filtering = FALSE;
186 		goto out;
187 	}
188 
189 out:
190 	return hw->mac.tx_pkt_filtering;
191 }
192 
193 /**
194  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
195  *  @hw: pointer to the HW structure
196  *  @buffer: pointer to the host interface
197  *  @length: size of the buffer
198  *
199  *  Writes the DHCP information to the host interface.
200  **/
201 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
202                                       u16 length)
203 {
204 	struct e1000_host_mng_command_header hdr;
205 	s32 ret_val;
206 	u32 hicr;
207 
208 	DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
209 
210 	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
211 	hdr.command_length = length;
212 	hdr.reserved1 = 0;
213 	hdr.reserved2 = 0;
214 	hdr.checksum = 0;
215 
216 	/* Enable the host interface */
217 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
218 	if (ret_val)
219 		goto out;
220 
221 	/* Populate the host interface with the contents of "buffer". */
222 	ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
223 	                                  sizeof(hdr), &(hdr.checksum));
224 	if (ret_val)
225 		goto out;
226 
227 	/* Write the manageability command header */
228 	ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
229 	if (ret_val)
230 		goto out;
231 
232 	/* Tell the ARC a new command is pending. */
233 	hicr = E1000_READ_REG(hw, E1000_HICR);
234 	E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
235 
236 out:
237 	return ret_val;
238 }
239 
240 /**
241  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
242  *  @hw: pointer to the HW structure
243  *  @hdr: pointer to the host interface command header
244  *
245  *  Writes the command header after does the checksum calculation.
246  **/
247 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
248                                     struct e1000_host_mng_command_header *hdr)
249 {
250 	u16 i, length = sizeof(struct e1000_host_mng_command_header);
251 
252 	DEBUGFUNC("e1000_mng_write_cmd_header_generic");
253 
254 	/* Write the whole command header structure with new checksum. */
255 
256 	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
257 
258 	length >>= 2;
259 	/* Write the relevant command block into the ram area. */
260 	for (i = 0; i < length; i++) {
261 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
262 		                            *((u32 *) hdr + i));
263 		E1000_WRITE_FLUSH(hw);
264 	}
265 
266 	return E1000_SUCCESS;
267 }
268 
269 /**
270  *  e1000_mng_host_if_write_generic - Write to the manageability host interface
271  *  @hw: pointer to the HW structure
272  *  @buffer: pointer to the host interface buffer
273  *  @length: size of the buffer
274  *  @offset: location in the buffer to write to
275  *  @sum: sum of the data (not checksum)
276  *
277  *  This function writes the buffer content at the offset given on the host if.
278  *  It also does alignment considerations to do the writes in most efficient
279  *  way.  Also fills up the sum of the buffer in *buffer parameter.
280  **/
281 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
282                                     u16 length, u16 offset, u8 *sum)
283 {
284 	u8 *tmp;
285 	u8 *bufptr = buffer;
286 	u32 data = 0;
287 	s32 ret_val = E1000_SUCCESS;
288 	u16 remaining, i, j, prev_bytes;
289 
290 	DEBUGFUNC("e1000_mng_host_if_write_generic");
291 
292 	/* sum = only sum of the data and it is not checksum */
293 
294 	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
295 		ret_val = -E1000_ERR_PARAM;
296 		goto out;
297 	}
298 
299 	tmp = (u8 *)&data;
300 	prev_bytes = offset & 0x3;
301 	offset >>= 2;
302 
303 	if (prev_bytes) {
304 		data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
305 		for (j = prev_bytes; j < sizeof(u32); j++) {
306 			*(tmp + j) = *bufptr++;
307 			*sum += *(tmp + j);
308 		}
309 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
310 		length -= j - prev_bytes;
311 		offset++;
312 	}
313 
314 	remaining = length & 0x3;
315 	length -= remaining;
316 
317 	/* Calculate length in DWORDs */
318 	length >>= 2;
319 
320 	/*
321 	 * The device driver writes the relevant command block into the
322 	 * ram area.
323 	 */
324 	for (i = 0; i < length; i++) {
325 		for (j = 0; j < sizeof(u32); j++) {
326 			*(tmp + j) = *bufptr++;
327 			*sum += *(tmp + j);
328 		}
329 
330 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
331 		                            data);
332 	}
333 	if (remaining) {
334 		for (j = 0; j < sizeof(u32); j++) {
335 			if (j < remaining)
336 				*(tmp + j) = *bufptr++;
337 			else
338 				*(tmp + j) = 0;
339 
340 			*sum += *(tmp + j);
341 		}
342 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
343 	}
344 
345 out:
346 	return ret_val;
347 }
348 
349 /**
350  *  e1000_enable_mng_pass_thru - Check if management passthrough is needed
351  *  @hw: pointer to the HW structure
352  *
353  *  Verifies the hardware needs to leave interface enabled so that frames can
354  *  be directed to and from the management interface.
355  **/
356 bool 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 		goto out;
371 
372 	if (hw->mac.has_fwsm) {
373 		fwsm = E1000_READ_REG(hw, E1000_FWSM);
374 		factps = E1000_READ_REG(hw, E1000_FACTPS);
375 
376 		if (!(factps & E1000_FACTPS_MNGCG) &&
377 		    ((fwsm & E1000_FWSM_MODE_MASK) ==
378 		     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
379 			ret_val = TRUE;
380 			goto out;
381 		}
382 	} else if ((hw->mac.type == e1000_82574) ||
383 		   (hw->mac.type == e1000_82583)) {
384 		u16 data;
385 
386 		factps = E1000_READ_REG(hw, E1000_FACTPS);
387 		e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
388 
389 		if (!(factps & E1000_FACTPS_MNGCG) &&
390 		    ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
391 		     (e1000_mng_mode_pt << 13))) {
392 			ret_val = TRUE;
393 			goto out;
394 		}
395 	} else if ((manc & E1000_MANC_SMBUS_EN) &&
396 		    !(manc & E1000_MANC_ASF_EN)) {
397 			ret_val = TRUE;
398 			goto out;
399 	}
400 
401 out:
402 	return ret_val;
403 }
404 
405 /**
406  *  e1000_host_interface_command - Writes buffer to host interface
407  *  @hw: pointer to the HW structure
408  *  @buffer: contains a command to write
409  *  @length: the byte length of the buffer, must be multiple of 4 bytes
410  *
411  *  Writes a buffer to the Host Interface.  Upon success, returns E1000_SUCCESS
412  *  else returns E1000_ERR_HOST_INTERFACE_COMMAND.
413  **/
414 s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
415 {
416 	u32 hicr, i;
417 	s32 ret_val = E1000_SUCCESS;
418 
419 	DEBUGFUNC("e1000_host_interface_command");
420 
421 	if (!(hw->mac.arc_subsystem_valid)) {
422 		DEBUGOUT("Hardware doesn't support host interface command.\n");
423 		goto out;
424 	}
425 
426 	if (!hw->mac.asf_firmware_present) {
427 		DEBUGOUT("Firmware is not present.\n");
428 		goto out;
429 	}
430 
431 	if (length == 0 || length & 0x3 ||
432 	    length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
433 		DEBUGOUT("Buffer length failure.\n");
434 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
435 		goto out;
436 	}
437 
438 	/* Check that the host interface is enabled. */
439 	hicr = E1000_READ_REG(hw, E1000_HICR);
440 	if ((hicr & E1000_HICR_EN) == 0) {
441 		DEBUGOUT("E1000_HOST_EN bit disabled.\n");
442 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
443 		goto out;
444 	}
445 
446 	/* Calculate length in DWORDs */
447 	length >>= 2;
448 
449 	/*
450 	 * The device driver writes the relevant command block
451 	 * into the ram area.
452 	 */
453 	for (i = 0; i < length; i++)
454 		E1000_WRITE_REG_ARRAY_DWORD(hw,
455 		                            E1000_HOST_IF,
456 		                            i,
457 		                            *((u32 *)buffer + i));
458 
459 	/* Setting this bit tells the ARC that a new command is pending. */
460 	E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
461 
462 	for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
463 		hicr = E1000_READ_REG(hw, E1000_HICR);
464 		if (!(hicr & E1000_HICR_C))
465 			break;
466 		msec_delay(1);
467 	}
468 
469 	/* Check command successful completion. */
470 	if (i == E1000_HI_COMMAND_TIMEOUT ||
471 	    (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
472 		DEBUGOUT("Command has failed with no status valid.\n");
473 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
474 		goto out;
475 	}
476 
477 	for (i = 0; i < length; i++)
478 		*((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
479 		                                                  E1000_HOST_IF,
480 		                                                  i);
481 
482 out:
483 	return ret_val;
484 }
485 
486