gpx e1000 driver.
[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,
163                                                            offset + i);
164         }
165         hdr_csum = hdr->checksum;
166         hdr->checksum = 0;
167         csum = e1000_calculate_checksum((u8 *)hdr,
168                                         E1000_MNG_DHCP_COOKIE_LENGTH);
169         /*
170          * If either the checksums or signature don't match, then
171          * the cookie area isn't considered valid, in which case we
172          * take the safe route of assuming Tx filtering is enabled.
173          */
174         if (hdr_csum != csum)
175                 goto out;
176         if (hdr->signature != E1000_IAMT_SIGNATURE)
177                 goto out;
178
179         /* Cookie area is valid, make the final check for filtering. */
180         if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
181                 tx_filter = false;
182
183 out:
184         hw->mac.tx_pkt_filtering = tx_filter;
185         return tx_filter;
186 }
187
188 /**
189  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
190  *  @hw: pointer to the HW structure
191  *  @buffer: pointer to the host interface
192  *  @length: size of the buffer
193  *
194  *  Writes the DHCP information to the host interface.
195  **/
196 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
197                                       u16 length)
198 {
199         struct e1000_host_mng_command_header hdr;
200         s32 ret_val;
201         u32 hicr;
202
203         DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
204
205         hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
206         hdr.command_length = length;
207         hdr.reserved1 = 0;
208         hdr.reserved2 = 0;
209         hdr.checksum = 0;
210
211         /* Enable the host interface */
212         ret_val = hw->mac.ops.mng_enable_host_if(hw);
213         if (ret_val)
214                 goto out;
215
216         /* Populate the host interface with the contents of "buffer". */
217         ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
218                                           sizeof(hdr), &(hdr.checksum));
219         if (ret_val)
220                 goto out;
221
222         /* Write the manageability command header */
223         ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
224         if (ret_val)
225                 goto out;
226
227         /* Tell the ARC a new command is pending. */
228         hicr = E1000_READ_REG(hw, E1000_HICR);
229         E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
230
231 out:
232         return ret_val;
233 }
234
235 /**
236  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
237  *  @hw: pointer to the HW structure
238  *  @hdr: pointer to the host interface command header
239  *
240  *  Writes the command header after does the checksum calculation.
241  **/
242 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
243                                     struct e1000_host_mng_command_header *hdr)
244 {
245         u16 i, length = sizeof(struct e1000_host_mng_command_header);
246
247         DEBUGFUNC("e1000_mng_write_cmd_header_generic");
248
249         /* Write the whole command header structure with new checksum. */
250
251         hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
252
253         length >>= 2;
254         /* Write the relevant command block into the ram area. */
255         for (i = 0; i < length; i++) {
256                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
257                                             *((u32 *) hdr + i));
258                 E1000_WRITE_FLUSH(hw);
259         }
260
261         return E1000_SUCCESS;
262 }
263
264 /**
265  *  e1000_mng_host_if_write_generic - Write to the manageability host interface
266  *  @hw: pointer to the HW structure
267  *  @buffer: pointer to the host interface buffer
268  *  @length: size of the buffer
269  *  @offset: location in the buffer to write to
270  *  @sum: sum of the data (not checksum)
271  *
272  *  This function writes the buffer content at the offset given on the host if.
273  *  It also does alignment considerations to do the writes in most efficient
274  *  way.  Also fills up the sum of the buffer in *buffer parameter.
275  **/
276 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
277                                     u16 length, u16 offset, u8 *sum)
278 {
279         u8 *tmp;
280         u8 *bufptr = buffer;
281         u32 data = 0;
282         s32 ret_val = E1000_SUCCESS;
283         u16 remaining, i, j, prev_bytes;
284
285         DEBUGFUNC("e1000_mng_host_if_write_generic");
286
287         /* sum = only sum of the data and it is not checksum */
288
289         if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
290                 ret_val = -E1000_ERR_PARAM;
291                 goto out;
292         }
293
294         tmp = (u8 *)&data;
295         prev_bytes = offset & 0x3;
296         offset >>= 2;
297
298         if (prev_bytes) {
299                 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
300                 for (j = prev_bytes; j < sizeof(u32); j++) {
301                         *(tmp + j) = *bufptr++;
302                         *sum += *(tmp + j);
303                 }
304                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
305                 length -= j - prev_bytes;
306                 offset++;
307         }
308
309         remaining = length & 0x3;
310         length -= remaining;
311
312         /* Calculate length in DWORDs */
313         length >>= 2;
314
315         /*
316          * The device driver writes the relevant command block into the
317          * ram area.
318          */
319         for (i = 0; i < length; i++) {
320                 for (j = 0; j < sizeof(u32); j++) {
321                         *(tmp + j) = *bufptr++;
322                         *sum += *(tmp + j);
323                 }
324
325                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
326                                             data);
327         }
328         if (remaining) {
329                 for (j = 0; j < sizeof(u32); j++) {
330                         if (j < remaining)
331                                 *(tmp + j) = *bufptr++;
332                         else
333                                 *(tmp + j) = 0;
334
335                         *sum += *(tmp + j);
336                 }
337                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
338         }
339
340 out:
341         return ret_val;
342 }
343
344 /**
345  *  e1000_enable_mng_pass_thru - Enable processing of ARP's
346  *  @hw: pointer to the HW structure
347  *
348  *  Verifies the hardware needs to allow ARPs to be processed by the host.
349  **/
350 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
351 {
352         u32 manc;
353         u32 fwsm, factps;
354         bool ret_val = false;
355
356         DEBUGFUNC("e1000_enable_mng_pass_thru");
357
358         if (!hw->mac.asf_firmware_present)
359                 goto out;
360
361         manc = E1000_READ_REG(hw, E1000_MANC);
362
363         if (!(manc & E1000_MANC_RCV_TCO_EN) ||
364             !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
365                 goto out;
366
367         if (hw->mac.arc_subsystem_valid) {
368                 fwsm = E1000_READ_REG(hw, E1000_FWSM);
369                 factps = E1000_READ_REG(hw, E1000_FACTPS);
370
371                 if (!(factps & E1000_FACTPS_MNGCG) &&
372                     ((fwsm & E1000_FWSM_MODE_MASK) ==
373                      (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
374                         ret_val = true;
375                         goto out;
376                 }
377         } else {
378                 if ((manc & E1000_MANC_SMBUS_EN) &&
379                     !(manc & E1000_MANC_ASF_EN)) {
380                         ret_val = true;
381                         goto out;
382                 }
383         }
384
385 out:
386         return ret_val;
387 }
388
389 #endif