em(4)/emx(4): Update ig_hal to Intel's 7.1.7
[dragonfly.git] / sys / dev / netif / ig_hal / e1000_manage.c
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