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