75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/******************************************************************************
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
49b7860084dbba18bc00b29413d6182197f9fe93Robert Mustacchi Copyright (c) 2001-2015, Intel Corporation
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi All rights reserved.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi Redistribution and use in source and binary forms, with or without
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi modification, are permitted provided that the following conditions are met:
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 1. Redistributions of source code must retain the above copyright notice,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi this list of conditions and the following disclaimer.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 2. Redistributions in binary form must reproduce the above copyright
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi notice, this list of conditions and the following disclaimer in the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi documentation and/or other materials provided with the distribution.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi contributors may be used to endorse or promote products derived from
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi this software without specific prior written permission.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi POSSIBILITY OF SUCH DAMAGE.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi******************************************************************************/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/*$FreeBSD$*/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi#include "e1000_api.h"
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_calculate_checksum - Calculate checksum for buffer
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @buffer: pointer to EEPROM
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @length: size of EEPROM to calculate a checksum for
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Calculates the checksum for some buffer on a specified length. The
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * checksum calculated is returned.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchiu8 e1000_calculate_checksum(u8 *buffer, u32 length)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 i;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 sum = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_calculate_checksum");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!buffer)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < length; i++)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi sum += buffer[i];
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return (u8) (0 - sum);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_mng_enable_host_if_generic - Checks host interface is enabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * This function checks whether the HOST IF is enabled for command operation
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and also checks whether the previous command is completed. It busy waits
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in case of previous command is not completed.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 hicr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 i;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_mng_enable_host_if_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->mac.arc_subsystem_valid) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("ARC subsystem not valid.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check that the host interface is enabled. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hicr & E1000_HICR_EN)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("E1000_HOST_EN bit disabled.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* check the previous command is completed */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hicr & E1000_HICR_C))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay_irq(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Previous command timeout failed .\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_check_mng_mode_generic - Generic check management mode
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Reads the firmware semaphore register and returns TRUE (>0) if
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * manageability is enabled, else FALSE (0).
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchibool e1000_check_mng_mode_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_check_mng_mode_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return (fwsm & E1000_FWSM_MODE_MASK) ==
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Enables packet filtering on transmit packets if manageability is enabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and host interface is enabled.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchibool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 *buffer = (u32 *)&hw->mng_cookie;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 offset;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val, hdr_csum, csum;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 i, len;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.tx_pkt_filtering = TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* No manageability, no filtering */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->mac.ops.check_mng_mode(hw)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.tx_pkt_filtering = FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return hw->mac.tx_pkt_filtering;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* If we can't read from the host interface for whatever
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * reason, disable filtering.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_mng_enable_host_if_generic(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val != E1000_SUCCESS) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.tx_pkt_filtering = FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return hw->mac.tx_pkt_filtering;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Read in the header. Length and offset are in dwords. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < len; i++)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset + i);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hdr_csum = hdr->checksum;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hdr->checksum = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi csum = e1000_calculate_checksum((u8 *)hdr,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_MNG_DHCP_COOKIE_LENGTH);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* If either the checksums or signature don't match, then
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * the cookie area isn't considered valid, in which case we
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * take the safe route of assuming Tx filtering is enabled.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.tx_pkt_filtering = TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return hw->mac.tx_pkt_filtering;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Cookie area is valid, make the final check for filtering. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hw->mac.tx_pkt_filtering = FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return hw->mac.tx_pkt_filtering;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_mng_write_cmd_header_generic - Writes manageability command header
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hdr: pointer to the host interface command header
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes the command header after does the checksum calculation.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_host_mng_command_header *hdr)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 i, length = sizeof(struct e1000_host_mng_command_header);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_mng_write_cmd_header_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Write the whole command header structure with new checksum. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length >>= 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Write the relevant command block into the ram area. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < length; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *((u32 *) hdr + i));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_mng_host_if_write_generic - Write to the manageability host interface
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @buffer: pointer to the host interface buffer
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @length: size of the buffer
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @offset: location in the buffer to write to
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @sum: sum of the data (not checksum)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * This function writes the buffer content at the offset given on the host if.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * It also does alignment considerations to do the writes in most efficient
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * way. Also fills up the sum of the buffer in *buffer parameter.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 length, u16 offset, u8 *sum)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 *tmp;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u8 *bufptr = buffer;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 data = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 remaining, i, j, prev_bytes;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_mng_host_if_write_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* sum = only sum of the data and it is not checksum */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_PARAM;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi tmp = (u8 *)&data;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi prev_bytes = offset & 0x3;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset >>= 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (prev_bytes) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (j = prev_bytes; j < sizeof(u32); j++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *(tmp + j) = *bufptr++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *sum += *(tmp + j);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length -= j - prev_bytes;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi offset++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi remaining = length & 0x3;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length -= remaining;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Calculate length in DWORDs */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length >>= 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* The device driver writes the relevant command block into the
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * ram area.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < length; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (j = 0; j < sizeof(u32); j++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *(tmp + j) = *bufptr++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *sum += *(tmp + j);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (remaining) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (j = 0; j < sizeof(u32); j++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (j < remaining)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *(tmp + j) = *bufptr++;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi else
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *(tmp + j) = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *sum += *(tmp + j);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi data);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @buffer: pointer to the host interface
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @length: size of the buffer
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes the DHCP information to the host interface.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 length)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi struct e1000_host_mng_command_header hdr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 hicr;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hdr.command_length = length;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hdr.reserved1 = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hdr.reserved2 = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hdr.checksum = 0;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Enable the host interface */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_mng_enable_host_if_generic(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Populate the host interface with the contents of "buffer". */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_mng_host_if_write_generic(hw, buffer, length,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi sizeof(hdr), &(hdr.checksum));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Write the manageability command header */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ret_val = e1000_mng_write_cmd_header_generic(hw, &hdr);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (ret_val)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Tell the ARC a new command is pending. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_enable_mng_pass_thru - Check if management passthrough is needed
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Verifies the hardware needs to leave interface enabled so that frames can
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * be directed to and from the management interface.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchibool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 manc;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 fwsm, factps;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_enable_mng_pass_thru");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->mac.asf_firmware_present)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi manc = E1000_READ_REG(hw, E1000_MANC);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(manc & E1000_MANC_RCV_TCO_EN))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->mac.has_fwsm) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi fwsm = E1000_READ_REG(hw, E1000_FWSM);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi factps = E1000_READ_REG(hw, E1000_FACTPS);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(factps & E1000_FACTPS_MNGCG) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ((fwsm & E1000_FWSM_MODE_MASK) ==
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else if ((hw->mac.type == e1000_82574) ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (hw->mac.type == e1000_82583)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u16 data;
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi s32 ret_val;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi factps = E1000_READ_REG(hw, E1000_FACTPS);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi if (ret_val)
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(factps & E1000_FACTPS_MNGCG) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (e1000_mng_mode_pt << 13)))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi } else if ((manc & E1000_MANC_SMBUS_EN) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi !(manc & E1000_MANC_ASF_EN)) {
c124a83e09115de88ecccd4f689983f42a1d53bdRobert Mustacchi return TRUE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return FALSE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_host_interface_command - Writes buffer to host interface
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @buffer: contains a command to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @length: the byte length of the buffer, must be multiple of 4 bytes
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * else returns E1000_ERR_HOST_INTERFACE_COMMAND.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 hicr, i;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_host_interface_command");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hw->mac.arc_subsystem_valid)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Hardware doesn't support host interface command.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!hw->mac.asf_firmware_present) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Firmware is not present.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (length == 0 || length & 0x3 ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Buffer length failure.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check that the host interface is enabled. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hicr & E1000_HICR_EN)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("E1000_HOST_EN bit disabled.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Calculate length in DWORDs */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length >>= 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* The device driver writes the relevant command block
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * into the ram area.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < length; i++)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *((u32 *)buffer + i));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Setting this bit tells the ARC that a new command is pending. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hicr & E1000_HICR_C))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check command successful completion. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i == E1000_HI_COMMAND_TIMEOUT ||
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Command has failed with no status valid.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < length; i++)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_HOST_IF,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi/**
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * e1000_load_firmware - Writes proxy FW code buffer to host interface
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * and execute.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @hw: pointer to the HW structure
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @buffer: contains a firmware to write
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * @length: the byte length of the buffer, must be multiple of 4 bytes
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi **/
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchis32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi{
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi u32 hicr, hibba, fwsm, icr, i;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGFUNC("e1000_load_firmware");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (hw->mac.type < e1000_i210) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Hardware doesn't support loading FW by the driver\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check that the host interface is enabled. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hicr & E1000_HICR_EN)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("E1000_HOST_EN bit disabled.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_CONFIG;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("Buffer length failure.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_INVALID_ARGUMENT;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Clear notification from ROM-FW by reading ICR register */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi icr = E1000_READ_REG(hw, E1000_ICR_V2);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Reset ROM-FW */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr |= E1000_HICR_FW_RESET_ENABLE;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr |= E1000_HICR_FW_RESET;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_FLUSH(hw);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Wait till MAC notifies about its readiness after ROM-FW reset */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi icr = E1000_READ_REG(hw, E1000_ICR_V2);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (icr & E1000_ICR_MNG)
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check for timeout */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i == E1000_HI_COMMAND_TIMEOUT) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("FW reset failed.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Wait till MAC is ready to accept new FW code */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi fwsm = E1000_READ_REG(hw, E1000_FWSM);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if ((fwsm & E1000_FWSM_FW_VALID) &&
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT ==
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_FWSM_HI_EN_ONLY_MODE))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check for timeout */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i == E1000_HI_COMMAND_TIMEOUT) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("FW reset failed.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Calculate length in DWORDs */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi length >>= 2;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* The device driver writes the relevant FW code block
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi * into the ram area in DWORDs via 1kB ram addressing window.
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < length; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Point to correct 1kB ram window */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hibba = E1000_HI_FW_BASE_ADDRESS +
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi ((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) *
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi (i / E1000_HI_FW_BLOCK_DWORD_LENGTH));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_HIBBA, hibba);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi i % E1000_HI_FW_BLOCK_DWORD_LENGTH,
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi *((u32 *)buffer + i));
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Setting this bit tells the ARC that a new FW is ready to execute. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (!(hicr & E1000_HICR_C))
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi break;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi msec_delay(1);
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi /* Check for successful FW start. */
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi if (i == E1000_HI_COMMAND_TIMEOUT) {
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi DEBUGOUT("New FW did not start within timeout period.\n");
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi }
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi return E1000_SUCCESS;
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi}
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi
75eba5b6d79ed4d2ce3daf7b2806306b6b69a938Robert Mustacchi