BNX2X: usability fixups
[akaros.git] / kern / drivers / net / e1000 / e1000_manage.c
1 /*******************************************************************************
2
3   Intel PRO/1000 Linux driver
4   Copyright(c) 1999 - 2008 Intel Corporation.
5
6   This program is free software; you can redistribute it and/or modify it
7   under the terms and conditions of the GNU General Public License,
8   version 2, as published by the Free Software Foundation.
9
10   This program is distributed in the hope it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13   more details.
14
15   You should have received a copy of the GNU General Public License along with
16   this program; if not, write to the Free Software Foundation, Inc.,
17   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18
19   The full GNU General Public License is included in this distribution in
20   the file called "COPYING".
21
22   Contact Information:
23   Linux NICS <linux.nics@intel.com>
24   e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
25   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26
27 *******************************************************************************/
28
29 FILE_LICENCE(GPL2_OR_LATER);
30
31 #if 0
32
33 #include "e1000_api.h"
34
35 static u8 e1000_calculate_checksum(u8 * buffer, u32 length);
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 static 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         /* Check that the host interface is enabled. */
80         hicr = E1000_READ_REG(hw, E1000_HICR);
81         if ((hicr & E1000_HICR_EN) == 0) {
82                 DEBUGOUT("E1000_HOST_EN bit disabled.\n");
83                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
84                 goto out;
85         }
86         /* check the previous command is completed */
87         for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
88                 hicr = E1000_READ_REG(hw, E1000_HICR);
89                 if (!(hicr & E1000_HICR_C))
90                         break;
91                 msec_delay_irq(1);
92         }
93
94         if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
95                 DEBUGOUT("Previous command timeout failed .\n");
96                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
97                 goto out;
98         }
99
100 out:
101         return ret_val;
102 }
103
104 /**
105  *  e1000_check_mng_mode_generic - Generic check management mode
106  *  @hw: pointer to the HW structure
107  *
108  *  Reads the firmware semaphore register and returns true (>0) if
109  *  manageability is enabled, else false (0).
110  **/
111 bool e1000_check_mng_mode_generic(struct e1000_hw * hw)
112 {
113         u32 fwsm;
114
115         DEBUGFUNC("e1000_check_mng_mode_generic");
116
117         fwsm = E1000_READ_REG(hw, E1000_FWSM);
118
119         return (fwsm & E1000_FWSM_MODE_MASK) ==
120                 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
121 }
122
123 /**
124  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX
125  *  @hw: pointer to the HW structure
126  *
127  *  Enables packet filtering on transmit packets if manageability is enabled
128  *  and host interface is enabled.
129  **/
130 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw * hw)
131 {
132         struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
133         u32 *buffer = (u32 *) & hw->mng_cookie;
134         u32 offset;
135         s32 ret_val, hdr_csum, csum;
136         u8 i, len;
137         bool tx_filter = true;
138
139         DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
140
141         /* No manageability, no filtering */
142         if (!hw->mac.ops.check_mng_mode(hw)) {
143                 tx_filter = false;
144                 goto out;
145         }
146
147         /*
148          * If we can't read from the host interface for whatever
149          * reason, disable filtering.
150          */
151         ret_val = hw->mac.ops.mng_enable_host_if(hw);
152         if (ret_val != E1000_SUCCESS) {
153                 tx_filter = false;
154                 goto out;
155         }
156
157         /* Read in the header.  Length and offset are in dwords. */
158         len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
159         offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
160         for (i = 0; i < len; i++) {
161                 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
162                                                                                                    E1000_HOST_IF, offset + i);
163         }
164         hdr_csum = hdr->checksum;
165         hdr->checksum = 0;
166         csum = e1000_calculate_checksum((u8 *) hdr, E1000_MNG_DHCP_COOKIE_LENGTH);
167         /*
168          * If either the checksums or signature don't match, then
169          * the cookie area isn't considered valid, in which case we
170          * take the safe route of assuming Tx filtering is enabled.
171          */
172         if (hdr_csum != csum)
173                 goto out;
174         if (hdr->signature != E1000_IAMT_SIGNATURE)
175                 goto out;
176
177         /* Cookie area is valid, make the final check for filtering. */
178         if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
179                 tx_filter = false;
180
181 out:
182         hw->mac.tx_pkt_filtering = tx_filter;
183         return tx_filter;
184 }
185
186 /**
187  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
188  *  @hw: pointer to the HW structure
189  *  @buffer: pointer to the host interface
190  *  @length: size of the buffer
191  *
192  *  Writes the DHCP information to the host interface.
193  **/
194 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw, u8 * buffer,
195                                                                           u16 length)
196 {
197         struct e1000_host_mng_command_header hdr;
198         s32 ret_val;
199         u32 hicr;
200
201         DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
202
203         hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
204         hdr.command_length = length;
205         hdr.reserved1 = 0;
206         hdr.reserved2 = 0;
207         hdr.checksum = 0;
208
209         /* Enable the host interface */
210         ret_val = hw->mac.ops.mng_enable_host_if(hw);
211         if (ret_val)
212                 goto out;
213
214         /* Populate the host interface with the contents of "buffer". */
215         ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
216                                                                                         sizeof(hdr), &(hdr.checksum));
217         if (ret_val)
218                 goto out;
219
220         /* Write the manageability command header */
221         ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
222         if (ret_val)
223                 goto out;
224
225         /* Tell the ARC a new command is pending. */
226         hicr = E1000_READ_REG(hw, E1000_HICR);
227         E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
228
229 out:
230         return ret_val;
231 }
232
233 /**
234  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
235  *  @hw: pointer to the HW structure
236  *  @hdr: pointer to the host interface command header
237  *
238  *  Writes the command header after does the checksum calculation.
239  **/
240 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw * hw,
241                                                                            struct e1000_host_mng_command_header *
242                                                                            hdr)
243 {
244         u16 i, length = sizeof(struct e1000_host_mng_command_header);
245
246         DEBUGFUNC("e1000_mng_write_cmd_header_generic");
247
248         /* Write the whole command header structure with new checksum. */
249
250         hdr->checksum = e1000_calculate_checksum((u8 *) hdr, length);
251
252         length >>= 2;
253         /* Write the relevant command block into the ram area. */
254         for (i = 0; i < length; i++) {
255                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, *((u32 *) hdr + i));
256                 E1000_WRITE_FLUSH(hw);
257         }
258
259         return E1000_SUCCESS;
260 }
261
262 /**
263  *  e1000_mng_host_if_write_generic - Write to the manageability host interface
264  *  @hw: pointer to the HW structure
265  *  @buffer: pointer to the host interface buffer
266  *  @length: size of the buffer
267  *  @offset: location in the buffer to write to
268  *  @sum: sum of the data (not checksum)
269  *
270  *  This function writes the buffer content at the offset given on the host if.
271  *  It also does alignment considerations to do the writes in most efficient
272  *  way.  Also fills up the sum of the buffer in *buffer parameter.
273  **/
274 s32 e1000_mng_host_if_write_generic(struct e1000_hw * hw, u8 * buffer,
275                                                                         u16 length, u16 offset, u8 * sum)
276 {
277         u8 *tmp;
278         u8 *bufptr = buffer;
279         u32 data = 0;
280         s32 ret_val = E1000_SUCCESS;
281         u16 remaining, i, j, prev_bytes;
282
283         DEBUGFUNC("e1000_mng_host_if_write_generic");
284
285         /* sum = only sum of the data and it is not checksum */
286
287         if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
288                 ret_val = -E1000_ERR_PARAM;
289                 goto out;
290         }
291
292         tmp = (u8 *) & data;
293         prev_bytes = offset & 0x3;
294         offset >>= 2;
295
296         if (prev_bytes) {
297                 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
298                 for (j = prev_bytes; j < sizeof(u32); j++) {
299                         *(tmp + j) = *bufptr++;
300                         *sum += *(tmp + j);
301                 }
302                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
303                 length -= j - prev_bytes;
304                 offset++;
305         }
306
307         remaining = length & 0x3;
308         length -= remaining;
309
310         /* Calculate length in DWORDs */
311         length >>= 2;
312
313         /*
314          * The device driver writes the relevant command block into the
315          * ram area.
316          */
317         for (i = 0; i < length; i++) {
318                 for (j = 0; j < sizeof(u32); j++) {
319                         *(tmp + j) = *bufptr++;
320                         *sum += *(tmp + j);
321                 }
322
323                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
324         }
325         if (remaining) {
326                 for (j = 0; j < sizeof(u32); j++) {
327                         if (j < remaining)
328                                 *(tmp + j) = *bufptr++;
329                         else
330                                 *(tmp + j) = 0;
331
332                         *sum += *(tmp + j);
333                 }
334                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
335         }
336
337 out:
338         return ret_val;
339 }
340
341 /**
342  *  e1000_enable_mng_pass_thru - Enable processing of ARP's
343  *  @hw: pointer to the HW structure
344  *
345  *  Verifies the hardware needs to allow ARPs to be processed by the host.
346  **/
347 bool e1000_enable_mng_pass_thru(struct e1000_hw * hw)
348 {
349         u32 manc;
350         u32 fwsm, factps;
351         bool ret_val = false;
352
353         DEBUGFUNC("e1000_enable_mng_pass_thru");
354
355         if (!hw->mac.asf_firmware_present)
356                 goto out;
357
358         manc = E1000_READ_REG(hw, E1000_MANC);
359
360         if (!(manc & E1000_MANC_RCV_TCO_EN) ||
361                 !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
362                 goto out;
363
364         if (hw->mac.arc_subsystem_valid) {
365                 fwsm = E1000_READ_REG(hw, E1000_FWSM);
366                 factps = E1000_READ_REG(hw, E1000_FACTPS);
367
368                 if (!(factps & E1000_FACTPS_MNGCG) &&
369                         ((fwsm & E1000_FWSM_MODE_MASK) ==
370                          (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
371                         ret_val = true;
372                         goto out;
373                 }
374         } else {
375                 if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) {
376                         ret_val = true;
377                         goto out;
378                 }
379         }
380
381 out:
382         return ret_val;
383 }
384
385 #endif