xref: /dragonfly/sys/dev/netif/ig_hal/e1000_manage.c (revision 36a3d1d6)
1 /******************************************************************************
2 
3   Copyright (c) 2001-2008, 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 	/* Check that the host interface is enabled. */
82 	hicr = E1000_READ_REG(hw, E1000_HICR);
83 	if ((hicr & E1000_HICR_EN) == 0) {
84 		DEBUGOUT("E1000_HOST_EN bit disabled.\n");
85 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
86 		goto out;
87 	}
88 	/* check the previous command is completed */
89 	for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
90 		hicr = E1000_READ_REG(hw, E1000_HICR);
91 		if (!(hicr & E1000_HICR_C))
92 			break;
93 		msec_delay_irq(1);
94 	}
95 
96 	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
97 		DEBUGOUT("Previous command timeout failed .\n");
98 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
99 		goto out;
100 	}
101 
102 out:
103 	return ret_val;
104 }
105 
106 /**
107  *  e1000_check_mng_mode_generic - Generic check management mode
108  *  @hw: pointer to the HW structure
109  *
110  *  Reads the firmware semaphore register and returns TRUE (>0) if
111  *  manageability is enabled, else FALSE (0).
112  **/
113 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
114 {
115 	u32 fwsm;
116 
117 	DEBUGFUNC("e1000_check_mng_mode_generic");
118 
119 	fwsm = E1000_READ_REG(hw, E1000_FWSM);
120 
121 	return (fwsm & E1000_FWSM_MODE_MASK) ==
122 	        (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
123 }
124 
125 /**
126  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX
127  *  @hw: pointer to the HW structure
128  *
129  *  Enables packet filtering on transmit packets if manageability is enabled
130  *  and host interface is enabled.
131  **/
132 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
133 {
134 	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
135 	u32 *buffer = (u32 *)&hw->mng_cookie;
136 	u32 offset;
137 	s32 ret_val, hdr_csum, csum;
138 	u8 i, len;
139 	bool tx_filter = TRUE;
140 
141 	DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
142 
143 	/* No manageability, no filtering */
144 	if (!hw->mac.ops.check_mng_mode(hw)) {
145 		tx_filter = FALSE;
146 		goto out;
147 	}
148 
149 	/*
150 	 * If we can't read from the host interface for whatever
151 	 * reason, disable filtering.
152 	 */
153 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
154 	if (ret_val != E1000_SUCCESS) {
155 		tx_filter = FALSE;
156 		goto out;
157 	}
158 
159 	/* Read in the header.  Length and offset are in dwords. */
160 	len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
161 	offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
162 	for (i = 0; i < len; i++) {
163 		*(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
164 		                                           E1000_HOST_IF,
165 		                                           offset + i);
166 	}
167 	hdr_csum = hdr->checksum;
168 	hdr->checksum = 0;
169 	csum = e1000_calculate_checksum((u8 *)hdr,
170 	                                E1000_MNG_DHCP_COOKIE_LENGTH);
171 	/*
172 	 * If either the checksums or signature don't match, then
173 	 * the cookie area isn't considered valid, in which case we
174 	 * take the safe route of assuming Tx filtering is enabled.
175 	 */
176 	if (hdr_csum != csum)
177 		goto out;
178 	if (hdr->signature != E1000_IAMT_SIGNATURE)
179 		goto out;
180 
181 	/* Cookie area is valid, make the final check for filtering. */
182 	if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
183 		tx_filter = FALSE;
184 
185 out:
186 	hw->mac.tx_pkt_filtering = tx_filter;
187 	return tx_filter;
188 }
189 
190 /**
191  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
192  *  @hw: pointer to the HW structure
193  *  @buffer: pointer to the host interface
194  *  @length: size of the buffer
195  *
196  *  Writes the DHCP information to the host interface.
197  **/
198 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
199                                       u16 length)
200 {
201 	struct e1000_host_mng_command_header hdr;
202 	s32 ret_val;
203 	u32 hicr;
204 
205 	DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
206 
207 	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
208 	hdr.command_length = length;
209 	hdr.reserved1 = 0;
210 	hdr.reserved2 = 0;
211 	hdr.checksum = 0;
212 
213 	/* Enable the host interface */
214 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
215 	if (ret_val)
216 		goto out;
217 
218 	/* Populate the host interface with the contents of "buffer". */
219 	ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
220 	                                  sizeof(hdr), &(hdr.checksum));
221 	if (ret_val)
222 		goto out;
223 
224 	/* Write the manageability command header */
225 	ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
226 	if (ret_val)
227 		goto out;
228 
229 	/* Tell the ARC a new command is pending. */
230 	hicr = E1000_READ_REG(hw, E1000_HICR);
231 	E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
232 
233 out:
234 	return ret_val;
235 }
236 
237 /**
238  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
239  *  @hw: pointer to the HW structure
240  *  @hdr: pointer to the host interface command header
241  *
242  *  Writes the command header after does the checksum calculation.
243  **/
244 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
245                                     struct e1000_host_mng_command_header *hdr)
246 {
247 	u16 i, length = sizeof(struct e1000_host_mng_command_header);
248 
249 	DEBUGFUNC("e1000_mng_write_cmd_header_generic");
250 
251 	/* Write the whole command header structure with new checksum. */
252 
253 	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
254 
255 	length >>= 2;
256 	/* Write the relevant command block into the ram area. */
257 	for (i = 0; i < length; i++) {
258 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
259 		                            *((u32 *) hdr + i));
260 		E1000_WRITE_FLUSH(hw);
261 	}
262 
263 	return E1000_SUCCESS;
264 }
265 
266 /**
267  *  e1000_mng_host_if_write_generic - Write to the manageability host interface
268  *  @hw: pointer to the HW structure
269  *  @buffer: pointer to the host interface buffer
270  *  @length: size of the buffer
271  *  @offset: location in the buffer to write to
272  *  @sum: sum of the data (not checksum)
273  *
274  *  This function writes the buffer content at the offset given on the host if.
275  *  It also does alignment considerations to do the writes in most efficient
276  *  way.  Also fills up the sum of the buffer in *buffer parameter.
277  **/
278 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
279                                     u16 length, u16 offset, u8 *sum)
280 {
281 	u8 *tmp;
282 	u8 *bufptr = buffer;
283 	u32 data = 0;
284 	s32 ret_val = E1000_SUCCESS;
285 	u16 remaining, i, j, prev_bytes;
286 
287 	DEBUGFUNC("e1000_mng_host_if_write_generic");
288 
289 	/* sum = only sum of the data and it is not checksum */
290 
291 	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
292 		ret_val = -E1000_ERR_PARAM;
293 		goto out;
294 	}
295 
296 	tmp = (u8 *)&data;
297 	prev_bytes = offset & 0x3;
298 	offset >>= 2;
299 
300 	if (prev_bytes) {
301 		data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
302 		for (j = prev_bytes; j < sizeof(u32); j++) {
303 			*(tmp + j) = *bufptr++;
304 			*sum += *(tmp + j);
305 		}
306 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
307 		length -= j - prev_bytes;
308 		offset++;
309 	}
310 
311 	remaining = length & 0x3;
312 	length -= remaining;
313 
314 	/* Calculate length in DWORDs */
315 	length >>= 2;
316 
317 	/*
318 	 * The device driver writes the relevant command block into the
319 	 * ram area.
320 	 */
321 	for (i = 0; i < length; i++) {
322 		for (j = 0; j < sizeof(u32); j++) {
323 			*(tmp + j) = *bufptr++;
324 			*sum += *(tmp + j);
325 		}
326 
327 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
328 		                            data);
329 	}
330 	if (remaining) {
331 		for (j = 0; j < sizeof(u32); j++) {
332 			if (j < remaining)
333 				*(tmp + j) = *bufptr++;
334 			else
335 				*(tmp + j) = 0;
336 
337 			*sum += *(tmp + j);
338 		}
339 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
340 	}
341 
342 out:
343 	return ret_val;
344 }
345 
346 /**
347  *  e1000_enable_mng_pass_thru - Enable processing of ARP's
348  *  @hw: pointer to the HW structure
349  *
350  *  Verifies the hardware needs to allow ARPs to be processed by the host.
351  **/
352 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
353 {
354 	u32 manc;
355 	u32 fwsm, factps;
356 	bool ret_val = FALSE;
357 
358 	DEBUGFUNC("e1000_enable_mng_pass_thru");
359 
360 	if (!hw->mac.asf_firmware_present)
361 		goto out;
362 
363 	manc = E1000_READ_REG(hw, E1000_MANC);
364 
365 	if (!(manc & E1000_MANC_RCV_TCO_EN) ||
366 	    !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
367 		goto out;
368 
369 	if (hw->mac.arc_subsystem_valid) {
370 		fwsm = E1000_READ_REG(hw, E1000_FWSM);
371 		factps = E1000_READ_REG(hw, E1000_FACTPS);
372 
373 		if (!(factps & E1000_FACTPS_MNGCG) &&
374 		    ((fwsm & E1000_FWSM_MODE_MASK) ==
375 		     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
376 			ret_val = TRUE;
377 			goto out;
378 		}
379 	} else {
380 		if ((manc & E1000_MANC_SMBUS_EN) &&
381 		    !(manc & E1000_MANC_ASF_EN)) {
382 			ret_val = TRUE;
383 			goto out;
384 		}
385 	}
386 
387 out:
388 	return ret_val;
389 }
390 
391