xref: /freebsd/sys/dev/e1000/e1000_manage.c (revision 8cfa0ad2)
18cfa0ad2SJack F Vogel /******************************************************************************
28cfa0ad2SJack F Vogel 
38cfa0ad2SJack F Vogel   Copyright (c) 2001-2008, Intel Corporation
48cfa0ad2SJack F Vogel   All rights reserved.
58cfa0ad2SJack F Vogel 
68cfa0ad2SJack F Vogel   Redistribution and use in source and binary forms, with or without
78cfa0ad2SJack F Vogel   modification, are permitted provided that the following conditions are met:
88cfa0ad2SJack F Vogel 
98cfa0ad2SJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
108cfa0ad2SJack F Vogel       this list of conditions and the following disclaimer.
118cfa0ad2SJack F Vogel 
128cfa0ad2SJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
138cfa0ad2SJack F Vogel       notice, this list of conditions and the following disclaimer in the
148cfa0ad2SJack F Vogel       documentation and/or other materials provided with the distribution.
158cfa0ad2SJack F Vogel 
168cfa0ad2SJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
178cfa0ad2SJack F Vogel       contributors may be used to endorse or promote products derived from
188cfa0ad2SJack F Vogel       this software without specific prior written permission.
198cfa0ad2SJack F Vogel 
208cfa0ad2SJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
218cfa0ad2SJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228cfa0ad2SJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238cfa0ad2SJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248cfa0ad2SJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258cfa0ad2SJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268cfa0ad2SJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278cfa0ad2SJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288cfa0ad2SJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298cfa0ad2SJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
308cfa0ad2SJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
318cfa0ad2SJack F Vogel 
328cfa0ad2SJack F Vogel ******************************************************************************/
338cfa0ad2SJack F Vogel /*$FreeBSD$*/
348cfa0ad2SJack F Vogel 
358cfa0ad2SJack F Vogel #include "e1000_api.h"
368cfa0ad2SJack F Vogel 
378cfa0ad2SJack F Vogel static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
388cfa0ad2SJack F Vogel 
398cfa0ad2SJack F Vogel /**
408cfa0ad2SJack F Vogel  *  e1000_calculate_checksum - Calculate checksum for buffer
418cfa0ad2SJack F Vogel  *  @buffer: pointer to EEPROM
428cfa0ad2SJack F Vogel  *  @length: size of EEPROM to calculate a checksum for
438cfa0ad2SJack F Vogel  *
448cfa0ad2SJack F Vogel  *  Calculates the checksum for some buffer on a specified length.  The
458cfa0ad2SJack F Vogel  *  checksum calculated is returned.
468cfa0ad2SJack F Vogel  **/
478cfa0ad2SJack F Vogel static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
488cfa0ad2SJack F Vogel {
498cfa0ad2SJack F Vogel 	u32 i;
508cfa0ad2SJack F Vogel 	u8  sum = 0;
518cfa0ad2SJack F Vogel 
528cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_calculate_checksum");
538cfa0ad2SJack F Vogel 
548cfa0ad2SJack F Vogel 	if (!buffer)
558cfa0ad2SJack F Vogel 		return 0;
568cfa0ad2SJack F Vogel 
578cfa0ad2SJack F Vogel 	for (i = 0; i < length; i++)
588cfa0ad2SJack F Vogel 		sum += buffer[i];
598cfa0ad2SJack F Vogel 
608cfa0ad2SJack F Vogel 	return (u8) (0 - sum);
618cfa0ad2SJack F Vogel }
628cfa0ad2SJack F Vogel 
638cfa0ad2SJack F Vogel /**
648cfa0ad2SJack F Vogel  *  e1000_mng_enable_host_if_generic - Checks host interface is enabled
658cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
668cfa0ad2SJack F Vogel  *
678cfa0ad2SJack F Vogel  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
688cfa0ad2SJack F Vogel  *
698cfa0ad2SJack F Vogel  *  This function checks whether the HOST IF is enabled for command operation
708cfa0ad2SJack F Vogel  *  and also checks whether the previous command is completed.  It busy waits
718cfa0ad2SJack F Vogel  *  in case of previous command is not completed.
728cfa0ad2SJack F Vogel  **/
738cfa0ad2SJack F Vogel s32 e1000_mng_enable_host_if_generic(struct e1000_hw * hw)
748cfa0ad2SJack F Vogel {
758cfa0ad2SJack F Vogel 	u32 hicr;
768cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
778cfa0ad2SJack F Vogel 	u8  i;
788cfa0ad2SJack F Vogel 
798cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_mng_enable_host_if_generic");
808cfa0ad2SJack F Vogel 
818cfa0ad2SJack F Vogel 	/* Check that the host interface is enabled. */
828cfa0ad2SJack F Vogel 	hicr = E1000_READ_REG(hw, E1000_HICR);
838cfa0ad2SJack F Vogel 	if ((hicr & E1000_HICR_EN) == 0) {
848cfa0ad2SJack F Vogel 		DEBUGOUT("E1000_HOST_EN bit disabled.\n");
858cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
868cfa0ad2SJack F Vogel 		goto out;
878cfa0ad2SJack F Vogel 	}
888cfa0ad2SJack F Vogel 	/* check the previous command is completed */
898cfa0ad2SJack F Vogel 	for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
908cfa0ad2SJack F Vogel 		hicr = E1000_READ_REG(hw, E1000_HICR);
918cfa0ad2SJack F Vogel 		if (!(hicr & E1000_HICR_C))
928cfa0ad2SJack F Vogel 			break;
938cfa0ad2SJack F Vogel 		msec_delay_irq(1);
948cfa0ad2SJack F Vogel 	}
958cfa0ad2SJack F Vogel 
968cfa0ad2SJack F Vogel 	if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
978cfa0ad2SJack F Vogel 		DEBUGOUT("Previous command timeout failed .\n");
988cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
998cfa0ad2SJack F Vogel 		goto out;
1008cfa0ad2SJack F Vogel 	}
1018cfa0ad2SJack F Vogel 
1028cfa0ad2SJack F Vogel out:
1038cfa0ad2SJack F Vogel 	return ret_val;
1048cfa0ad2SJack F Vogel }
1058cfa0ad2SJack F Vogel 
1068cfa0ad2SJack F Vogel /**
1078cfa0ad2SJack F Vogel  *  e1000_check_mng_mode_generic - Generic check management mode
1088cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1098cfa0ad2SJack F Vogel  *
1108cfa0ad2SJack F Vogel  *  Reads the firmware semaphore register and returns TRUE (>0) if
1118cfa0ad2SJack F Vogel  *  manageability is enabled, else FALSE (0).
1128cfa0ad2SJack F Vogel  **/
1138cfa0ad2SJack F Vogel bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
1148cfa0ad2SJack F Vogel {
1158cfa0ad2SJack F Vogel 	u32 fwsm;
1168cfa0ad2SJack F Vogel 
1178cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_check_mng_mode_generic");
1188cfa0ad2SJack F Vogel 
1198cfa0ad2SJack F Vogel 	fwsm = E1000_READ_REG(hw, E1000_FWSM);
1208cfa0ad2SJack F Vogel 
1218cfa0ad2SJack F Vogel 	return ((fwsm & E1000_FWSM_MODE_MASK) ==
1228cfa0ad2SJack F Vogel 	        (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
1238cfa0ad2SJack F Vogel }
1248cfa0ad2SJack F Vogel 
1258cfa0ad2SJack F Vogel /**
1268cfa0ad2SJack F Vogel  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX
1278cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1288cfa0ad2SJack F Vogel  *
1298cfa0ad2SJack F Vogel  *  Enables packet filtering on transmit packets if manageability is enabled
1308cfa0ad2SJack F Vogel  *  and host interface is enabled.
1318cfa0ad2SJack F Vogel  **/
1328cfa0ad2SJack F Vogel bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
1338cfa0ad2SJack F Vogel {
1348cfa0ad2SJack F Vogel 	struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
1358cfa0ad2SJack F Vogel 	u32 *buffer = (u32 *)&hw->mng_cookie;
1368cfa0ad2SJack F Vogel 	u32 offset;
1378cfa0ad2SJack F Vogel 	s32 ret_val, hdr_csum, csum;
1388cfa0ad2SJack F Vogel 	u8 i, len;
1398cfa0ad2SJack F Vogel 	bool tx_filter = TRUE;
1408cfa0ad2SJack F Vogel 
1418cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
1428cfa0ad2SJack F Vogel 
1438cfa0ad2SJack F Vogel 	/* No manageability, no filtering */
1448cfa0ad2SJack F Vogel 	if (!hw->mac.ops.check_mng_mode(hw)) {
1458cfa0ad2SJack F Vogel 		tx_filter = FALSE;
1468cfa0ad2SJack F Vogel 		goto out;
1478cfa0ad2SJack F Vogel 	}
1488cfa0ad2SJack F Vogel 
1498cfa0ad2SJack F Vogel 	/*
1508cfa0ad2SJack F Vogel 	 * If we can't read from the host interface for whatever
1518cfa0ad2SJack F Vogel 	 * reason, disable filtering.
1528cfa0ad2SJack F Vogel 	 */
1538cfa0ad2SJack F Vogel 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
1548cfa0ad2SJack F Vogel 	if (ret_val != E1000_SUCCESS) {
1558cfa0ad2SJack F Vogel 		tx_filter = FALSE;
1568cfa0ad2SJack F Vogel 		goto out;
1578cfa0ad2SJack F Vogel 	}
1588cfa0ad2SJack F Vogel 
1598cfa0ad2SJack F Vogel 	/* Read in the header.  Length and offset are in dwords. */
1608cfa0ad2SJack F Vogel 	len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
1618cfa0ad2SJack F Vogel 	offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
1628cfa0ad2SJack F Vogel 	for (i = 0; i < len; i++) {
1638cfa0ad2SJack F Vogel 		*(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
1648cfa0ad2SJack F Vogel 		                                           E1000_HOST_IF,
1658cfa0ad2SJack F Vogel 		                                           offset + i);
1668cfa0ad2SJack F Vogel 	}
1678cfa0ad2SJack F Vogel 	hdr_csum = hdr->checksum;
1688cfa0ad2SJack F Vogel 	hdr->checksum = 0;
1698cfa0ad2SJack F Vogel 	csum = e1000_calculate_checksum((u8 *)hdr,
1708cfa0ad2SJack F Vogel 	                                E1000_MNG_DHCP_COOKIE_LENGTH);
1718cfa0ad2SJack F Vogel 	/*
1728cfa0ad2SJack F Vogel 	 * If either the checksums or signature don't match, then
1738cfa0ad2SJack F Vogel 	 * the cookie area isn't considered valid, in which case we
1748cfa0ad2SJack F Vogel 	 * take the safe route of assuming Tx filtering is enabled.
1758cfa0ad2SJack F Vogel 	 */
1768cfa0ad2SJack F Vogel 	if (hdr_csum != csum)
1778cfa0ad2SJack F Vogel 		goto out;
1788cfa0ad2SJack F Vogel 	if (hdr->signature != E1000_IAMT_SIGNATURE)
1798cfa0ad2SJack F Vogel 		goto out;
1808cfa0ad2SJack F Vogel 
1818cfa0ad2SJack F Vogel 	/* Cookie area is valid, make the final check for filtering. */
1828cfa0ad2SJack F Vogel 	if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
1838cfa0ad2SJack F Vogel 		tx_filter = FALSE;
1848cfa0ad2SJack F Vogel 
1858cfa0ad2SJack F Vogel out:
1868cfa0ad2SJack F Vogel 	hw->mac.tx_pkt_filtering = tx_filter;
1878cfa0ad2SJack F Vogel 	return tx_filter;
1888cfa0ad2SJack F Vogel }
1898cfa0ad2SJack F Vogel 
1908cfa0ad2SJack F Vogel /**
1918cfa0ad2SJack F Vogel  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
1928cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
1938cfa0ad2SJack F Vogel  *  @buffer: pointer to the host interface
1948cfa0ad2SJack F Vogel  *  @length: size of the buffer
1958cfa0ad2SJack F Vogel  *
1968cfa0ad2SJack F Vogel  *  Writes the DHCP information to the host interface.
1978cfa0ad2SJack F Vogel  **/
1988cfa0ad2SJack F Vogel s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw, u8 *buffer,
1998cfa0ad2SJack F Vogel                                       u16 length)
2008cfa0ad2SJack F Vogel {
2018cfa0ad2SJack F Vogel 	struct e1000_host_mng_command_header hdr;
2028cfa0ad2SJack F Vogel 	s32 ret_val;
2038cfa0ad2SJack F Vogel 	u32 hicr;
2048cfa0ad2SJack F Vogel 
2058cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
2068cfa0ad2SJack F Vogel 
2078cfa0ad2SJack F Vogel 	hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
2088cfa0ad2SJack F Vogel 	hdr.command_length = length;
2098cfa0ad2SJack F Vogel 	hdr.reserved1 = 0;
2108cfa0ad2SJack F Vogel 	hdr.reserved2 = 0;
2118cfa0ad2SJack F Vogel 	hdr.checksum = 0;
2128cfa0ad2SJack F Vogel 
2138cfa0ad2SJack F Vogel 	/* Enable the host interface */
2148cfa0ad2SJack F Vogel 	ret_val = hw->mac.ops.mng_enable_host_if(hw);
2158cfa0ad2SJack F Vogel 	if (ret_val)
2168cfa0ad2SJack F Vogel 		goto out;
2178cfa0ad2SJack F Vogel 
2188cfa0ad2SJack F Vogel 	/* Populate the host interface with the contents of "buffer". */
2198cfa0ad2SJack F Vogel 	ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
2208cfa0ad2SJack F Vogel 	                                  sizeof(hdr), &(hdr.checksum));
2218cfa0ad2SJack F Vogel 	if (ret_val)
2228cfa0ad2SJack F Vogel 		goto out;
2238cfa0ad2SJack F Vogel 
2248cfa0ad2SJack F Vogel 	/* Write the manageability command header */
2258cfa0ad2SJack F Vogel 	ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
2268cfa0ad2SJack F Vogel 	if (ret_val)
2278cfa0ad2SJack F Vogel 		goto out;
2288cfa0ad2SJack F Vogel 
2298cfa0ad2SJack F Vogel 	/* Tell the ARC a new command is pending. */
2308cfa0ad2SJack F Vogel 	hicr = E1000_READ_REG(hw, E1000_HICR);
2318cfa0ad2SJack F Vogel 	E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
2328cfa0ad2SJack F Vogel 
2338cfa0ad2SJack F Vogel out:
2348cfa0ad2SJack F Vogel 	return ret_val;
2358cfa0ad2SJack F Vogel }
2368cfa0ad2SJack F Vogel 
2378cfa0ad2SJack F Vogel /**
2388cfa0ad2SJack F Vogel  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
2398cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
2408cfa0ad2SJack F Vogel  *  @hdr: pointer to the host interface command header
2418cfa0ad2SJack F Vogel  *
2428cfa0ad2SJack F Vogel  *  Writes the command header after does the checksum calculation.
2438cfa0ad2SJack F Vogel  **/
2448cfa0ad2SJack F Vogel s32 e1000_mng_write_cmd_header_generic(struct e1000_hw * hw,
2458cfa0ad2SJack F Vogel                                     struct e1000_host_mng_command_header * hdr)
2468cfa0ad2SJack F Vogel {
2478cfa0ad2SJack F Vogel 	u16 i, length = sizeof(struct e1000_host_mng_command_header);
2488cfa0ad2SJack F Vogel 
2498cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_mng_write_cmd_header_generic");
2508cfa0ad2SJack F Vogel 
2518cfa0ad2SJack F Vogel 	/* Write the whole command header structure with new checksum. */
2528cfa0ad2SJack F Vogel 
2538cfa0ad2SJack F Vogel 	hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
2548cfa0ad2SJack F Vogel 
2558cfa0ad2SJack F Vogel 	length >>= 2;
2568cfa0ad2SJack F Vogel 	/* Write the relevant command block into the ram area. */
2578cfa0ad2SJack F Vogel 	for (i = 0; i < length; i++) {
2588cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
2598cfa0ad2SJack F Vogel 		                            *((u32 *) hdr + i));
2608cfa0ad2SJack F Vogel 		E1000_WRITE_FLUSH(hw);
2618cfa0ad2SJack F Vogel 	}
2628cfa0ad2SJack F Vogel 
2638cfa0ad2SJack F Vogel 	return E1000_SUCCESS;
2648cfa0ad2SJack F Vogel }
2658cfa0ad2SJack F Vogel 
2668cfa0ad2SJack F Vogel /**
2678cfa0ad2SJack F Vogel  *  e1000_mng_host_if_write_generic - Write to the manageability host interface
2688cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
2698cfa0ad2SJack F Vogel  *  @buffer: pointer to the host interface buffer
2708cfa0ad2SJack F Vogel  *  @length: size of the buffer
2718cfa0ad2SJack F Vogel  *  @offset: location in the buffer to write to
2728cfa0ad2SJack F Vogel  *  @sum: sum of the data (not checksum)
2738cfa0ad2SJack F Vogel  *
2748cfa0ad2SJack F Vogel  *  This function writes the buffer content at the offset given on the host if.
2758cfa0ad2SJack F Vogel  *  It also does alignment considerations to do the writes in most efficient
2768cfa0ad2SJack F Vogel  *  way.  Also fills up the sum of the buffer in *buffer parameter.
2778cfa0ad2SJack F Vogel  **/
2788cfa0ad2SJack F Vogel s32 e1000_mng_host_if_write_generic(struct e1000_hw * hw, u8 *buffer,
2798cfa0ad2SJack F Vogel                                     u16 length, u16 offset, u8 *sum)
2808cfa0ad2SJack F Vogel {
2818cfa0ad2SJack F Vogel 	u8 *tmp;
2828cfa0ad2SJack F Vogel 	u8 *bufptr = buffer;
2838cfa0ad2SJack F Vogel 	u32 data = 0;
2848cfa0ad2SJack F Vogel 	s32 ret_val = E1000_SUCCESS;
2858cfa0ad2SJack F Vogel 	u16 remaining, i, j, prev_bytes;
2868cfa0ad2SJack F Vogel 
2878cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_mng_host_if_write_generic");
2888cfa0ad2SJack F Vogel 
2898cfa0ad2SJack F Vogel 	/* sum = only sum of the data and it is not checksum */
2908cfa0ad2SJack F Vogel 
2918cfa0ad2SJack F Vogel 	if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
2928cfa0ad2SJack F Vogel 		ret_val = -E1000_ERR_PARAM;
2938cfa0ad2SJack F Vogel 		goto out;
2948cfa0ad2SJack F Vogel 	}
2958cfa0ad2SJack F Vogel 
2968cfa0ad2SJack F Vogel 	tmp = (u8 *)&data;
2978cfa0ad2SJack F Vogel 	prev_bytes = offset & 0x3;
2988cfa0ad2SJack F Vogel 	offset >>= 2;
2998cfa0ad2SJack F Vogel 
3008cfa0ad2SJack F Vogel 	if (prev_bytes) {
3018cfa0ad2SJack F Vogel 		data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
3028cfa0ad2SJack F Vogel 		for (j = prev_bytes; j < sizeof(u32); j++) {
3038cfa0ad2SJack F Vogel 			*(tmp + j) = *bufptr++;
3048cfa0ad2SJack F Vogel 			*sum += *(tmp + j);
3058cfa0ad2SJack F Vogel 		}
3068cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
3078cfa0ad2SJack F Vogel 		length -= j - prev_bytes;
3088cfa0ad2SJack F Vogel 		offset++;
3098cfa0ad2SJack F Vogel 	}
3108cfa0ad2SJack F Vogel 
3118cfa0ad2SJack F Vogel 	remaining = length & 0x3;
3128cfa0ad2SJack F Vogel 	length -= remaining;
3138cfa0ad2SJack F Vogel 
3148cfa0ad2SJack F Vogel 	/* Calculate length in DWORDs */
3158cfa0ad2SJack F Vogel 	length >>= 2;
3168cfa0ad2SJack F Vogel 
3178cfa0ad2SJack F Vogel 	/*
3188cfa0ad2SJack F Vogel 	 * The device driver writes the relevant command block into the
3198cfa0ad2SJack F Vogel 	 * ram area.
3208cfa0ad2SJack F Vogel 	 */
3218cfa0ad2SJack F Vogel 	for (i = 0; i < length; i++) {
3228cfa0ad2SJack F Vogel 		for (j = 0; j < sizeof(u32); j++) {
3238cfa0ad2SJack F Vogel 			*(tmp + j) = *bufptr++;
3248cfa0ad2SJack F Vogel 			*sum += *(tmp + j);
3258cfa0ad2SJack F Vogel 		}
3268cfa0ad2SJack F Vogel 
3278cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
3288cfa0ad2SJack F Vogel 	}
3298cfa0ad2SJack F Vogel 	if (remaining) {
3308cfa0ad2SJack F Vogel 		for (j = 0; j < sizeof(u32); j++) {
3318cfa0ad2SJack F Vogel 			if (j < remaining)
3328cfa0ad2SJack F Vogel 				*(tmp + j) = *bufptr++;
3338cfa0ad2SJack F Vogel 			else
3348cfa0ad2SJack F Vogel 				*(tmp + j) = 0;
3358cfa0ad2SJack F Vogel 
3368cfa0ad2SJack F Vogel 			*sum += *(tmp + j);
3378cfa0ad2SJack F Vogel 		}
3388cfa0ad2SJack F Vogel 		E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
3398cfa0ad2SJack F Vogel 	}
3408cfa0ad2SJack F Vogel 
3418cfa0ad2SJack F Vogel out:
3428cfa0ad2SJack F Vogel 	return ret_val;
3438cfa0ad2SJack F Vogel }
3448cfa0ad2SJack F Vogel 
3458cfa0ad2SJack F Vogel /**
3468cfa0ad2SJack F Vogel  *  e1000_enable_mng_pass_thru - Enable processing of ARP's
3478cfa0ad2SJack F Vogel  *  @hw: pointer to the HW structure
3488cfa0ad2SJack F Vogel  *
3498cfa0ad2SJack F Vogel  *  Verifies the hardware needs to allow ARPs to be processed by the host.
3508cfa0ad2SJack F Vogel  **/
3518cfa0ad2SJack F Vogel bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
3528cfa0ad2SJack F Vogel {
3538cfa0ad2SJack F Vogel 	u32 manc;
3548cfa0ad2SJack F Vogel 	u32 fwsm, factps;
3558cfa0ad2SJack F Vogel 	bool ret_val = FALSE;
3568cfa0ad2SJack F Vogel 
3578cfa0ad2SJack F Vogel 	DEBUGFUNC("e1000_enable_mng_pass_thru");
3588cfa0ad2SJack F Vogel 
3598cfa0ad2SJack F Vogel 	if (!hw->mac.asf_firmware_present)
3608cfa0ad2SJack F Vogel 		goto out;
3618cfa0ad2SJack F Vogel 
3628cfa0ad2SJack F Vogel 	manc = E1000_READ_REG(hw, E1000_MANC);
3638cfa0ad2SJack F Vogel 
3648cfa0ad2SJack F Vogel 	if (!(manc & E1000_MANC_RCV_TCO_EN) ||
3658cfa0ad2SJack F Vogel 	    !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
3668cfa0ad2SJack F Vogel 		goto out;
3678cfa0ad2SJack F Vogel 
3688cfa0ad2SJack F Vogel 	if (hw->mac.arc_subsystem_valid) {
3698cfa0ad2SJack F Vogel 		fwsm = E1000_READ_REG(hw, E1000_FWSM);
3708cfa0ad2SJack F Vogel 		factps = E1000_READ_REG(hw, E1000_FACTPS);
3718cfa0ad2SJack F Vogel 
3728cfa0ad2SJack F Vogel 		if (!(factps & E1000_FACTPS_MNGCG) &&
3738cfa0ad2SJack F Vogel 		    ((fwsm & E1000_FWSM_MODE_MASK) ==
3748cfa0ad2SJack F Vogel 		     (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
3758cfa0ad2SJack F Vogel 			ret_val = TRUE;
3768cfa0ad2SJack F Vogel 			goto out;
3778cfa0ad2SJack F Vogel 		}
3788cfa0ad2SJack F Vogel 	} else {
3798cfa0ad2SJack F Vogel 		if ((manc & E1000_MANC_SMBUS_EN) &&
3808cfa0ad2SJack F Vogel 		    !(manc & E1000_MANC_ASF_EN)) {
3818cfa0ad2SJack F Vogel 			ret_val = TRUE;
3828cfa0ad2SJack F Vogel 			goto out;
3838cfa0ad2SJack F Vogel 		}
3848cfa0ad2SJack F Vogel 	}
3858cfa0ad2SJack F Vogel 
3868cfa0ad2SJack F Vogel out:
3878cfa0ad2SJack F Vogel 	return ret_val;
3888cfa0ad2SJack F Vogel }
3898cfa0ad2SJack F Vogel 
390