Home | History | Annotate | Download | only in igb
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
      5  * The contents of this file are subject to the terms of the
      6  * Common Development and Distribution License (the "License").
      7  * You may not use this file except in compliance with the License.
      8  *
      9  * You can obtain a copy of the license at:
     10  *	http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When using or redistributing this file, you may do so under the
     15  * License only. No other modification of this header is permitted.
     16  *
     17  * If applicable, add the following below this CDDL HEADER, with the
     18  * fields enclosed by brackets "[]" replaced with your own identifying
     19  * information: Portions Copyright [yyyy] [name of copyright owner]
     20  *
     21  * CDDL HEADER END
     22  */
     23 
     24 /*
     25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     26  * Use is subject to license terms of the CDDL.
     27  */
     28 
     29 /* IntelVersion: 1.27 v2-9-8_2009-6-12 */
     30 
     31 #include "igb_api.h"
     32 
     33 static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
     34 
     35 /*
     36  * e1000_calculate_checksum - Calculate checksum for buffer
     37  * @buffer: pointer to EEPROM
     38  * @length: size of EEPROM to calculate a checksum for
     39  *
     40  * Calculates the checksum for some buffer on a specified length.  The
     41  * checksum calculated is returned.
     42  */
     43 static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
     44 {
     45 	u32 i;
     46 	u8  sum = 0;
     47 
     48 	DEBUGFUNC("e1000_calculate_checksum");
     49 
     50 	if (!buffer)
     51 		return (0);
     52 
     53 	for (i = 0; i < length; i++)
     54 		sum += buffer[i];
     55 
     56 	return (u8) (0 - sum);
     57 }
     58 
     59 /*
     60  * e1000_mng_enable_host_if_generic - Checks host interface is enabled
     61  * @hw: pointer to the HW structure
     62  *
     63  * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
     64  *
     65  * This function checks whether the HOST IF is enabled for command operation
     66  * and also checks whether the previous command is completed.  It busy waits
     67  * in case of previous command is not completed.
     68  */
     69 s32
     70 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
     71 {
     72 	u32 hicr;
     73 	s32 ret_val = E1000_SUCCESS;
     74 	u8  i;
     75 
     76 	DEBUGFUNC("e1000_mng_enable_host_if_generic");
     77 
     78 	/* Check that the host interface is enabled. */
     79 	hicr = E1000_READ_REG(hw, E1000_HICR);
     80 	if ((hicr & E1000_HICR_EN) == 0) {
     81 		DEBUGOUT("E1000_HOST_EN bit disabled.\n");
     82 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
     83 		goto out;
     84 	}
     85 	/* check the previous command is completed */
     86 	for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
     87 		hicr = E1000_READ_REG(hw, E1000_HICR);
     88 		if (!(hicr & E1000_HICR_C))
     89 			break;
     90 		msec_delay_irq(1);
     91 	}
     92 
     93 	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
     94 		DEBUGOUT("Previous command timeout failed .\n");
     95 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
     96 		goto out;
     97 	}
     98 
     99 out:
    100 	return (ret_val);
    101 }
    102 
    103 /*
    104  * e1000_check_mng_mode_generic - Generic check management mode
    105  * @hw: pointer to the HW structure
    106  *
    107  * Reads the firmware semaphore register and returns true (>0) if
    108  * manageability is enabled, else false (0).
    109  */
    110 bool
    111 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
    131 e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
    132 {
    133 	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
    134 	u32 *buffer = (u32 *)&hw->mng_cookie;
    135 	u32 offset;
    136 	s32 ret_val, hdr_csum, csum;
    137 	u8 i, len;
    138 	bool tx_filter = true;
    139 
    140 	DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
    141 
    142 	/* No manageability, no filtering */
    143 	if (!hw->mac.ops.check_mng_mode(hw)) {
    144 		tx_filter = false;
    145 		goto out;
    146 	}
    147 
    148 	/*
    149 	 * If we can't read from the host interface for whatever
    150 	 * reason, disable filtering.
    151 	 */
    152 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
    153 	if (ret_val != E1000_SUCCESS) {
    154 		tx_filter = false;
    155 		goto out;
    156 	}
    157 
    158 	/* Read in the header.  Length and offset are in dwords. */
    159 	len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
    160 	offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
    161 	for (i = 0; i < len; i++) {
    162 		*(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
    163 		    E1000_HOST_IF, 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
    197 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
    198     u16 length)
    199 {
    200 	struct e1000_host_mng_command_header hdr;
    201 	s32 ret_val;
    202 	u32 hicr;
    203 
    204 	DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
    205 
    206 	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
    207 	hdr.command_length = length;
    208 	hdr.reserved1 = 0;
    209 	hdr.reserved2 = 0;
    210 	hdr.checksum = 0;
    211 
    212 	/* Enable the host interface */
    213 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
    214 	if (ret_val)
    215 		goto out;
    216 
    217 	/* Populate the host interface with the contents of "buffer". */
    218 	ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
    219 	    sizeof (hdr), &(hdr.checksum));
    220 	if (ret_val)
    221 		goto out;
    222 
    223 	/* Write the manageability command header */
    224 	ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
    225 	if (ret_val)
    226 		goto out;
    227 
    228 	/* Tell the ARC a new command is pending. */
    229 	hicr = E1000_READ_REG(hw, E1000_HICR);
    230 	E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
    231 
    232 out:
    233 	return (ret_val);
    234 }
    235 
    236 /*
    237  * e1000_mng_write_cmd_header_generic - Writes manageability command header
    238  * @hw: pointer to the HW structure
    239  * @hdr: pointer to the host interface command header
    240  *
    241  * Writes the command header after does the checksum calculation.
    242  */
    243 s32
    244 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
    245     struct e1000_host_mng_command_header *hdr)
    246 {
    247 	u16 i, length = sizeof (struct e1000_host_mng_command_header);
    248 
    249 	DEBUGFUNC("e1000_mng_write_cmd_header_generic");
    250 
    251 	/* Write the whole command header structure with new checksum. */
    252 
    253 	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
    254 
    255 	length >>= 2;
    256 	/* Write the relevant command block into the ram area. */
    257 	for (i = 0; i < length; i++) {
    258 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
    259 		    *((u32 *)(uintptr_t)hdr + i));
    260 		E1000_WRITE_FLUSH(hw);
    261 	}
    262 
    263 	return (E1000_SUCCESS);
    264 }
    265 
    266 /*
    267  * e1000_mng_host_if_write_generic - Write to the manageability host interface
    268  * @hw: pointer to the HW structure
    269  * @buffer: pointer to the host interface buffer
    270  * @length: size of the buffer
    271  * @offset: location in the buffer to write to
    272  * @sum: sum of the data (not checksum)
    273  *
    274  * This function writes the buffer content at the offset given on the host if.
    275  * It also does alignment considerations to do the writes in most efficient
    276  * way.  Also fills up the sum of the buffer in *buffer parameter.
    277  */
    278 s32
    279 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
    280     u16 length, u16 offset, u8 *sum)
    281 {
    282 	u8 *tmp;
    283 	u8 *bufptr = buffer;
    284 	u32 data = 0;
    285 	s32 ret_val = E1000_SUCCESS;
    286 	u16 remaining, i, j, prev_bytes;
    287 
    288 	DEBUGFUNC("e1000_mng_host_if_write_generic");
    289 
    290 	/* sum = only sum of the data and it is not checksum */
    291 
    292 	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
    293 		ret_val = -E1000_ERR_PARAM;
    294 		goto out;
    295 	}
    296 
    297 	tmp = (u8 *)&data;
    298 	prev_bytes = offset & 0x3;
    299 	offset >>= 2;
    300 
    301 	if (prev_bytes) {
    302 		data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
    303 		for (j = prev_bytes; j < sizeof (u32); j++) {
    304 			*(tmp + j) = *bufptr++;
    305 			*sum += *(tmp + j);
    306 		}
    307 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
    308 		length -= j - prev_bytes;
    309 		offset++;
    310 	}
    311 
    312 	remaining = length & 0x3;
    313 	length -= remaining;
    314 
    315 	/* Calculate length in DWORDs */
    316 	length >>= 2;
    317 
    318 	/*
    319 	 * The device driver writes the relevant command block into the
    320 	 * ram area.
    321 	 */
    322 	for (i = 0; i < length; i++) {
    323 		for (j = 0; j < sizeof (u32); j++) {
    324 			*(tmp + j) = *bufptr++;
    325 			*sum += *(tmp + j);
    326 		}
    327 
    328 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
    329 		    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,
    341 		    offset + i, data);
    342 	}
    343 
    344 out:
    345 	return (ret_val);
    346 }
    347 
    348 /*
    349  * e1000_enable_mng_pass_thru - Enable processing of ARP's
    350  * @hw: pointer to the HW structure
    351  *
    352  * Verifies the hardware needs to allow ARPs to be processed by the host.
    353  */
    354 bool
    355 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
    356 {
    357 	u32 manc;
    358 	u32 fwsm, factps;
    359 	bool ret_val = false;
    360 
    361 	DEBUGFUNC("e1000_enable_mng_pass_thru");
    362 
    363 	if (!hw->mac.asf_firmware_present)
    364 		goto out;
    365 
    366 	manc = E1000_READ_REG(hw, E1000_MANC);
    367 
    368 	if (!(manc & E1000_MANC_RCV_TCO_EN) ||
    369 	    !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
    370 		goto out;
    371 
    372 	if (hw->mac.arc_subsystem_valid) {
    373 		fwsm = E1000_READ_REG(hw, E1000_FWSM);
    374 		factps = E1000_READ_REG(hw, E1000_FACTPS);
    375 
    376 		if (!(factps & E1000_FACTPS_MNGCG) &&
    377 		    ((fwsm & E1000_FWSM_MODE_MASK) ==
    378 		    (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
    379 			ret_val = true;
    380 			goto out;
    381 		}
    382 	} else {
    383 		if ((manc & E1000_MANC_SMBUS_EN) &&
    384 		    !(manc & E1000_MANC_ASF_EN)) {
    385 			ret_val = true;
    386 			goto out;
    387 		}
    388 	}
    389 
    390 out:
    391 	return (ret_val);
    392 }
    393