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: releng/9.0/sys/dev/e1000/e1000_manage.c 218530 2011-02-11 01:00:26Z jfv $*/
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
Cache object: 043f1019a8fb935b8a2290ed1cae7816
|