00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 FILE_LICENCE ( GPL2_ONLY );
00029
00030 #include "igb.h"
00031
00032 #if 0
00033
00034 static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
00045 {
00046 u32 i;
00047 u8 sum = 0;
00048
00049 DEBUGFUNC("igb_calculate_checksum");
00050
00051 if (!buffer)
00052 return 0;
00053
00054 for (i = 0; i < length; i++)
00055 sum += buffer[i];
00056
00057 return (u8) (0 - sum);
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
00071 {
00072 u32 hicr;
00073 s32 ret_val = E1000_SUCCESS;
00074 u8 i;
00075
00076 DEBUGFUNC("igb_mng_enable_host_if_generic");
00077
00078
00079 hicr = E1000_READ_REG(hw, E1000_HICR);
00080 if ((hicr & E1000_HICR_EN) == 0) {
00081 DEBUGOUT("E1000_HOST_EN bit disabled.\n");
00082 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
00083 goto out;
00084 }
00085
00086 for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
00087 hicr = E1000_READ_REG(hw, E1000_HICR);
00088 if (!(hicr & E1000_HICR_C))
00089 break;
00090 msec_delay_irq(1);
00091 }
00092
00093 if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
00094 DEBUGOUT("Previous command timeout failed .\n");
00095 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
00096 goto out;
00097 }
00098
00099 out:
00100 return ret_val;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
00111 {
00112 u32 fwsm;
00113
00114 DEBUGFUNC("igb_check_mng_mode_generic");
00115
00116 fwsm = E1000_READ_REG(hw, E1000_FWSM);
00117
00118 return (fwsm & E1000_FWSM_MODE_MASK) ==
00119 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
00130 {
00131 struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
00132 u32 *buffer = (u32 *)&hw->mng_cookie;
00133 u32 offset;
00134 s32 ret_val, hdr_csum, csum;
00135 u8 i, len;
00136 bool tx_filter = true;
00137
00138 DEBUGFUNC("igb_enable_tx_pkt_filtering_generic");
00139
00140
00141 if (!hw->mac.ops.check_mng_mode(hw)) {
00142 tx_filter = false;
00143 goto out;
00144 }
00145
00146
00147
00148
00149
00150 ret_val = hw->mac.ops.mng_enable_host_if(hw);
00151 if (ret_val != E1000_SUCCESS) {
00152 tx_filter = false;
00153 goto out;
00154 }
00155
00156
00157 len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
00158 offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
00159 for (i = 0; i < len; i++) {
00160 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
00161 E1000_HOST_IF,
00162 offset + i);
00163 }
00164 hdr_csum = hdr->checksum;
00165 hdr->checksum = 0;
00166 csum = e1000_calculate_checksum((u8 *)hdr,
00167 E1000_MNG_DHCP_COOKIE_LENGTH);
00168
00169
00170
00171
00172
00173 if (hdr_csum != csum)
00174 goto out;
00175 if (hdr->signature != E1000_IAMT_SIGNATURE)
00176 goto out;
00177
00178
00179 if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
00180 tx_filter = false;
00181
00182 out:
00183 hw->mac.tx_pkt_filtering = tx_filter;
00184 return tx_filter;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
00196 u16 length)
00197 {
00198 struct e1000_host_mng_command_header hdr;
00199 s32 ret_val;
00200 u32 hicr;
00201
00202 DEBUGFUNC("igb_mng_write_dhcp_info_generic");
00203
00204 hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
00205 hdr.command_length = length;
00206 hdr.reserved1 = 0;
00207 hdr.reserved2 = 0;
00208 hdr.checksum = 0;
00209
00210
00211 ret_val = hw->mac.ops.mng_enable_host_if(hw);
00212 if (ret_val)
00213 goto out;
00214
00215
00216 ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
00217 sizeof(hdr), &(hdr.checksum));
00218 if (ret_val)
00219 goto out;
00220
00221
00222 ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
00223 if (ret_val)
00224 goto out;
00225
00226
00227 hicr = E1000_READ_REG(hw, E1000_HICR);
00228 E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
00229
00230 out:
00231 return ret_val;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
00242 struct e1000_host_mng_command_header *hdr)
00243 {
00244 u16 i, length = sizeof(struct e1000_host_mng_command_header);
00245
00246 DEBUGFUNC("igb_mng_write_cmd_header_generic");
00247
00248
00249
00250 hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
00251
00252 length >>= 2;
00253
00254 for (i = 0; i < length; i++) {
00255 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
00256 *((u32 *) hdr + i));
00257 E1000_WRITE_FLUSH(hw);
00258 }
00259
00260 return E1000_SUCCESS;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
00276 u16 length, u16 offset, u8 *sum)
00277 {
00278 u8 *tmp;
00279 u8 *bufptr = buffer;
00280 u32 data = 0;
00281 s32 ret_val = E1000_SUCCESS;
00282 u16 remaining, i, j, prev_bytes;
00283
00284 DEBUGFUNC("igb_mng_host_if_write_generic");
00285
00286
00287
00288 if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
00289 ret_val = -E1000_ERR_PARAM;
00290 goto out;
00291 }
00292
00293 tmp = (u8 *)&data;
00294 prev_bytes = offset & 0x3;
00295 offset >>= 2;
00296
00297 if (prev_bytes) {
00298 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
00299 for (j = prev_bytes; j < sizeof(u32); j++) {
00300 *(tmp + j) = *bufptr++;
00301 *sum += *(tmp + j);
00302 }
00303 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
00304 length -= j - prev_bytes;
00305 offset++;
00306 }
00307
00308 remaining = length & 0x3;
00309 length -= remaining;
00310
00311
00312 length >>= 2;
00313
00314
00315
00316
00317
00318 for (i = 0; i < length; i++) {
00319 for (j = 0; j < sizeof(u32); j++) {
00320 *(tmp + j) = *bufptr++;
00321 *sum += *(tmp + j);
00322 }
00323
00324 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
00325 data);
00326 }
00327 if (remaining) {
00328 for (j = 0; j < sizeof(u32); j++) {
00329 if (j < remaining)
00330 *(tmp + j) = *bufptr++;
00331 else
00332 *(tmp + j) = 0;
00333
00334 *sum += *(tmp + j);
00335 }
00336 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
00337 }
00338
00339 out:
00340 return ret_val;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
00350 {
00351 u32 manc;
00352 u32 fwsm, factps;
00353 bool ret_val = false;
00354
00355 DEBUGFUNC("igb_enable_mng_pass_thru");
00356
00357 if (!hw->mac.asf_firmware_present)
00358 goto out;
00359
00360 manc = E1000_READ_REG(hw, E1000_MANC);
00361
00362 if (!(manc & E1000_MANC_RCV_TCO_EN) ||
00363 !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
00364 goto out;
00365
00366 if (hw->mac.arc_subsystem_valid) {
00367 fwsm = E1000_READ_REG(hw, E1000_FWSM);
00368 factps = E1000_READ_REG(hw, E1000_FACTPS);
00369
00370 if (!(factps & E1000_FACTPS_MNGCG) &&
00371 ((fwsm & E1000_FWSM_MODE_MASK) ==
00372 (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
00373 ret_val = true;
00374 goto out;
00375 }
00376 } else {
00377 if ((manc & E1000_MANC_SMBUS_EN) &&
00378 !(manc & E1000_MANC_ASF_EN)) {
00379 ret_val = true;
00380 goto out;
00381 }
00382 }
00383
00384 out:
00385 return ret_val;
00386 }
00387
00388 #endif