175eba5b6SRobert Mustacchi /****************************************************************************** 275eba5b6SRobert Mustacchi 3*42cc51e0SRobert Mustacchi Copyright (c) 2001-2015, Intel Corporation 475eba5b6SRobert Mustacchi All rights reserved. 575eba5b6SRobert Mustacchi 675eba5b6SRobert Mustacchi Redistribution and use in source and binary forms, with or without 775eba5b6SRobert Mustacchi modification, are permitted provided that the following conditions are met: 875eba5b6SRobert Mustacchi 975eba5b6SRobert Mustacchi 1. Redistributions of source code must retain the above copyright notice, 1075eba5b6SRobert Mustacchi this list of conditions and the following disclaimer. 1175eba5b6SRobert Mustacchi 1275eba5b6SRobert Mustacchi 2. Redistributions in binary form must reproduce the above copyright 1375eba5b6SRobert Mustacchi notice, this list of conditions and the following disclaimer in the 1475eba5b6SRobert Mustacchi documentation and/or other materials provided with the distribution. 1575eba5b6SRobert Mustacchi 1675eba5b6SRobert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its 1775eba5b6SRobert Mustacchi contributors may be used to endorse or promote products derived from 1875eba5b6SRobert Mustacchi this software without specific prior written permission. 1975eba5b6SRobert Mustacchi 2075eba5b6SRobert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2175eba5b6SRobert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2275eba5b6SRobert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2375eba5b6SRobert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2475eba5b6SRobert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2575eba5b6SRobert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2675eba5b6SRobert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2775eba5b6SRobert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2875eba5b6SRobert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2975eba5b6SRobert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3075eba5b6SRobert Mustacchi POSSIBILITY OF SUCH DAMAGE. 3175eba5b6SRobert Mustacchi 3275eba5b6SRobert Mustacchi ******************************************************************************/ 3375eba5b6SRobert Mustacchi /*$FreeBSD$*/ 3475eba5b6SRobert Mustacchi 3575eba5b6SRobert Mustacchi #include "e1000_api.h" 3675eba5b6SRobert Mustacchi /** 3775eba5b6SRobert Mustacchi * e1000_calculate_checksum - Calculate checksum for buffer 3875eba5b6SRobert Mustacchi * @buffer: pointer to EEPROM 3975eba5b6SRobert Mustacchi * @length: size of EEPROM to calculate a checksum for 4075eba5b6SRobert Mustacchi * 4175eba5b6SRobert Mustacchi * Calculates the checksum for some buffer on a specified length. The 4275eba5b6SRobert Mustacchi * checksum calculated is returned. 4375eba5b6SRobert Mustacchi **/ 4475eba5b6SRobert Mustacchi u8 e1000_calculate_checksum(u8 *buffer, u32 length) 4575eba5b6SRobert Mustacchi { 4675eba5b6SRobert Mustacchi u32 i; 4775eba5b6SRobert Mustacchi u8 sum = 0; 4875eba5b6SRobert Mustacchi 4975eba5b6SRobert Mustacchi DEBUGFUNC("e1000_calculate_checksum"); 5075eba5b6SRobert Mustacchi 5175eba5b6SRobert Mustacchi if (!buffer) 5275eba5b6SRobert Mustacchi return 0; 5375eba5b6SRobert Mustacchi 5475eba5b6SRobert Mustacchi for (i = 0; i < length; i++) 5575eba5b6SRobert Mustacchi sum += buffer[i]; 5675eba5b6SRobert Mustacchi 5775eba5b6SRobert Mustacchi return (u8) (0 - sum); 5875eba5b6SRobert Mustacchi } 5975eba5b6SRobert Mustacchi 6075eba5b6SRobert Mustacchi /** 6175eba5b6SRobert Mustacchi * e1000_mng_enable_host_if_generic - Checks host interface is enabled 6275eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 6375eba5b6SRobert Mustacchi * 6475eba5b6SRobert Mustacchi * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND 6575eba5b6SRobert Mustacchi * 6675eba5b6SRobert Mustacchi * This function checks whether the HOST IF is enabled for command operation 6775eba5b6SRobert Mustacchi * and also checks whether the previous command is completed. It busy waits 6875eba5b6SRobert Mustacchi * in case of previous command is not completed. 6975eba5b6SRobert Mustacchi **/ 7075eba5b6SRobert Mustacchi s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw) 7175eba5b6SRobert Mustacchi { 7275eba5b6SRobert Mustacchi u32 hicr; 7375eba5b6SRobert Mustacchi u8 i; 7475eba5b6SRobert Mustacchi 7575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_mng_enable_host_if_generic"); 7675eba5b6SRobert Mustacchi 7775eba5b6SRobert Mustacchi if (!hw->mac.arc_subsystem_valid) { 7875eba5b6SRobert Mustacchi DEBUGOUT("ARC subsystem not valid.\n"); 7975eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 8075eba5b6SRobert Mustacchi } 8175eba5b6SRobert Mustacchi 8275eba5b6SRobert Mustacchi /* Check that the host interface is enabled. */ 8375eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 8475eba5b6SRobert Mustacchi if (!(hicr & E1000_HICR_EN)) { 8575eba5b6SRobert Mustacchi DEBUGOUT("E1000_HOST_EN bit disabled.\n"); 8675eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 8775eba5b6SRobert Mustacchi } 8875eba5b6SRobert Mustacchi /* check the previous command is completed */ 8975eba5b6SRobert Mustacchi for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { 9075eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 9175eba5b6SRobert Mustacchi if (!(hicr & E1000_HICR_C)) 9275eba5b6SRobert Mustacchi break; 9375eba5b6SRobert Mustacchi msec_delay_irq(1); 9475eba5b6SRobert Mustacchi } 9575eba5b6SRobert Mustacchi 9675eba5b6SRobert Mustacchi if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 9775eba5b6SRobert Mustacchi DEBUGOUT("Previous command timeout failed .\n"); 9875eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 9975eba5b6SRobert Mustacchi } 10075eba5b6SRobert Mustacchi 10175eba5b6SRobert Mustacchi return E1000_SUCCESS; 10275eba5b6SRobert Mustacchi } 10375eba5b6SRobert Mustacchi 10475eba5b6SRobert Mustacchi /** 10575eba5b6SRobert Mustacchi * e1000_check_mng_mode_generic - Generic check management mode 10675eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 10775eba5b6SRobert Mustacchi * 10875eba5b6SRobert Mustacchi * Reads the firmware semaphore register and returns TRUE (>0) if 10975eba5b6SRobert Mustacchi * manageability is enabled, else FALSE (0). 11075eba5b6SRobert Mustacchi **/ 11175eba5b6SRobert Mustacchi bool e1000_check_mng_mode_generic(struct e1000_hw *hw) 11275eba5b6SRobert Mustacchi { 11375eba5b6SRobert Mustacchi u32 fwsm = E1000_READ_REG(hw, E1000_FWSM); 11475eba5b6SRobert Mustacchi 11575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_check_mng_mode_generic"); 11675eba5b6SRobert Mustacchi 11775eba5b6SRobert Mustacchi 11875eba5b6SRobert Mustacchi return (fwsm & E1000_FWSM_MODE_MASK) == 11975eba5b6SRobert Mustacchi (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); 12075eba5b6SRobert Mustacchi } 12175eba5b6SRobert Mustacchi 12275eba5b6SRobert Mustacchi /** 12375eba5b6SRobert Mustacchi * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx 12475eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 12575eba5b6SRobert Mustacchi * 12675eba5b6SRobert Mustacchi * Enables packet filtering on transmit packets if manageability is enabled 12775eba5b6SRobert Mustacchi * and host interface is enabled. 12875eba5b6SRobert Mustacchi **/ 12975eba5b6SRobert Mustacchi bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw) 13075eba5b6SRobert Mustacchi { 13175eba5b6SRobert Mustacchi struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; 13275eba5b6SRobert Mustacchi u32 *buffer = (u32 *)&hw->mng_cookie; 13375eba5b6SRobert Mustacchi u32 offset; 13475eba5b6SRobert Mustacchi s32 ret_val, hdr_csum, csum; 13575eba5b6SRobert Mustacchi u8 i, len; 13675eba5b6SRobert Mustacchi 13775eba5b6SRobert Mustacchi DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic"); 13875eba5b6SRobert Mustacchi 13975eba5b6SRobert Mustacchi hw->mac.tx_pkt_filtering = TRUE; 14075eba5b6SRobert Mustacchi 14175eba5b6SRobert Mustacchi /* No manageability, no filtering */ 14275eba5b6SRobert Mustacchi if (!hw->mac.ops.check_mng_mode(hw)) { 14375eba5b6SRobert Mustacchi hw->mac.tx_pkt_filtering = FALSE; 14475eba5b6SRobert Mustacchi return hw->mac.tx_pkt_filtering; 14575eba5b6SRobert Mustacchi } 14675eba5b6SRobert Mustacchi 14775eba5b6SRobert Mustacchi /* If we can't read from the host interface for whatever 14875eba5b6SRobert Mustacchi * reason, disable filtering. 14975eba5b6SRobert Mustacchi */ 15075eba5b6SRobert Mustacchi ret_val = e1000_mng_enable_host_if_generic(hw); 15175eba5b6SRobert Mustacchi if (ret_val != E1000_SUCCESS) { 15275eba5b6SRobert Mustacchi hw->mac.tx_pkt_filtering = FALSE; 15375eba5b6SRobert Mustacchi return hw->mac.tx_pkt_filtering; 15475eba5b6SRobert Mustacchi } 15575eba5b6SRobert Mustacchi 15675eba5b6SRobert Mustacchi /* Read in the header. Length and offset are in dwords. */ 15775eba5b6SRobert Mustacchi len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; 15875eba5b6SRobert Mustacchi offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; 15975eba5b6SRobert Mustacchi for (i = 0; i < len; i++) 16075eba5b6SRobert Mustacchi *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 16175eba5b6SRobert Mustacchi offset + i); 16275eba5b6SRobert Mustacchi hdr_csum = hdr->checksum; 16375eba5b6SRobert Mustacchi hdr->checksum = 0; 16475eba5b6SRobert Mustacchi csum = e1000_calculate_checksum((u8 *)hdr, 16575eba5b6SRobert Mustacchi E1000_MNG_DHCP_COOKIE_LENGTH); 16675eba5b6SRobert Mustacchi /* If either the checksums or signature don't match, then 16775eba5b6SRobert Mustacchi * the cookie area isn't considered valid, in which case we 16875eba5b6SRobert Mustacchi * take the safe route of assuming Tx filtering is enabled. 16975eba5b6SRobert Mustacchi */ 17075eba5b6SRobert Mustacchi if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { 17175eba5b6SRobert Mustacchi hw->mac.tx_pkt_filtering = TRUE; 17275eba5b6SRobert Mustacchi return hw->mac.tx_pkt_filtering; 17375eba5b6SRobert Mustacchi } 17475eba5b6SRobert Mustacchi 17575eba5b6SRobert Mustacchi /* Cookie area is valid, make the final check for filtering. */ 17675eba5b6SRobert Mustacchi if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) 17775eba5b6SRobert Mustacchi hw->mac.tx_pkt_filtering = FALSE; 17875eba5b6SRobert Mustacchi 17975eba5b6SRobert Mustacchi return hw->mac.tx_pkt_filtering; 18075eba5b6SRobert Mustacchi } 18175eba5b6SRobert Mustacchi 18275eba5b6SRobert Mustacchi /** 18375eba5b6SRobert Mustacchi * e1000_mng_write_cmd_header_generic - Writes manageability command header 18475eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 18575eba5b6SRobert Mustacchi * @hdr: pointer to the host interface command header 18675eba5b6SRobert Mustacchi * 18775eba5b6SRobert Mustacchi * Writes the command header after does the checksum calculation. 18875eba5b6SRobert Mustacchi **/ 18975eba5b6SRobert Mustacchi s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw, 19075eba5b6SRobert Mustacchi struct e1000_host_mng_command_header *hdr) 19175eba5b6SRobert Mustacchi { 19275eba5b6SRobert Mustacchi u16 i, length = sizeof(struct e1000_host_mng_command_header); 19375eba5b6SRobert Mustacchi 19475eba5b6SRobert Mustacchi DEBUGFUNC("e1000_mng_write_cmd_header_generic"); 19575eba5b6SRobert Mustacchi 19675eba5b6SRobert Mustacchi /* Write the whole command header structure with new checksum. */ 19775eba5b6SRobert Mustacchi 19875eba5b6SRobert Mustacchi hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); 19975eba5b6SRobert Mustacchi 20075eba5b6SRobert Mustacchi length >>= 2; 20175eba5b6SRobert Mustacchi /* Write the relevant command block into the ram area. */ 20275eba5b6SRobert Mustacchi for (i = 0; i < length; i++) { 20375eba5b6SRobert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, 20475eba5b6SRobert Mustacchi *((u32 *) hdr + i)); 20575eba5b6SRobert Mustacchi E1000_WRITE_FLUSH(hw); 20675eba5b6SRobert Mustacchi } 20775eba5b6SRobert Mustacchi 20875eba5b6SRobert Mustacchi return E1000_SUCCESS; 20975eba5b6SRobert Mustacchi } 21075eba5b6SRobert Mustacchi 21175eba5b6SRobert Mustacchi /** 21275eba5b6SRobert Mustacchi * e1000_mng_host_if_write_generic - Write to the manageability host interface 21375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 21475eba5b6SRobert Mustacchi * @buffer: pointer to the host interface buffer 21575eba5b6SRobert Mustacchi * @length: size of the buffer 21675eba5b6SRobert Mustacchi * @offset: location in the buffer to write to 21775eba5b6SRobert Mustacchi * @sum: sum of the data (not checksum) 21875eba5b6SRobert Mustacchi * 21975eba5b6SRobert Mustacchi * This function writes the buffer content at the offset given on the host if. 22075eba5b6SRobert Mustacchi * It also does alignment considerations to do the writes in most efficient 22175eba5b6SRobert Mustacchi * way. Also fills up the sum of the buffer in *buffer parameter. 22275eba5b6SRobert Mustacchi **/ 22375eba5b6SRobert Mustacchi s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer, 22475eba5b6SRobert Mustacchi u16 length, u16 offset, u8 *sum) 22575eba5b6SRobert Mustacchi { 22675eba5b6SRobert Mustacchi u8 *tmp; 22775eba5b6SRobert Mustacchi u8 *bufptr = buffer; 22875eba5b6SRobert Mustacchi u32 data = 0; 22975eba5b6SRobert Mustacchi u16 remaining, i, j, prev_bytes; 23075eba5b6SRobert Mustacchi 23175eba5b6SRobert Mustacchi DEBUGFUNC("e1000_mng_host_if_write_generic"); 23275eba5b6SRobert Mustacchi 23375eba5b6SRobert Mustacchi /* sum = only sum of the data and it is not checksum */ 23475eba5b6SRobert Mustacchi 23575eba5b6SRobert Mustacchi if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) 23675eba5b6SRobert Mustacchi return -E1000_ERR_PARAM; 23775eba5b6SRobert Mustacchi 23875eba5b6SRobert Mustacchi tmp = (u8 *)&data; 23975eba5b6SRobert Mustacchi prev_bytes = offset & 0x3; 24075eba5b6SRobert Mustacchi offset >>= 2; 24175eba5b6SRobert Mustacchi 24275eba5b6SRobert Mustacchi if (prev_bytes) { 24375eba5b6SRobert Mustacchi data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset); 24475eba5b6SRobert Mustacchi for (j = prev_bytes; j < sizeof(u32); j++) { 24575eba5b6SRobert Mustacchi *(tmp + j) = *bufptr++; 24675eba5b6SRobert Mustacchi *sum += *(tmp + j); 24775eba5b6SRobert Mustacchi } 24875eba5b6SRobert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data); 24975eba5b6SRobert Mustacchi length -= j - prev_bytes; 25075eba5b6SRobert Mustacchi offset++; 25175eba5b6SRobert Mustacchi } 25275eba5b6SRobert Mustacchi 25375eba5b6SRobert Mustacchi remaining = length & 0x3; 25475eba5b6SRobert Mustacchi length -= remaining; 25575eba5b6SRobert Mustacchi 25675eba5b6SRobert Mustacchi /* Calculate length in DWORDs */ 25775eba5b6SRobert Mustacchi length >>= 2; 25875eba5b6SRobert Mustacchi 25975eba5b6SRobert Mustacchi /* The device driver writes the relevant command block into the 26075eba5b6SRobert Mustacchi * ram area. 26175eba5b6SRobert Mustacchi */ 26275eba5b6SRobert Mustacchi for (i = 0; i < length; i++) { 26375eba5b6SRobert Mustacchi for (j = 0; j < sizeof(u32); j++) { 26475eba5b6SRobert Mustacchi *(tmp + j) = *bufptr++; 26575eba5b6SRobert Mustacchi *sum += *(tmp + j); 26675eba5b6SRobert Mustacchi } 26775eba5b6SRobert Mustacchi 26875eba5b6SRobert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, 26975eba5b6SRobert Mustacchi data); 27075eba5b6SRobert Mustacchi } 27175eba5b6SRobert Mustacchi if (remaining) { 27275eba5b6SRobert Mustacchi for (j = 0; j < sizeof(u32); j++) { 27375eba5b6SRobert Mustacchi if (j < remaining) 27475eba5b6SRobert Mustacchi *(tmp + j) = *bufptr++; 27575eba5b6SRobert Mustacchi else 27675eba5b6SRobert Mustacchi *(tmp + j) = 0; 27775eba5b6SRobert Mustacchi 27875eba5b6SRobert Mustacchi *sum += *(tmp + j); 27975eba5b6SRobert Mustacchi } 28075eba5b6SRobert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, 28175eba5b6SRobert Mustacchi data); 28275eba5b6SRobert Mustacchi } 28375eba5b6SRobert Mustacchi 28475eba5b6SRobert Mustacchi return E1000_SUCCESS; 28575eba5b6SRobert Mustacchi } 28675eba5b6SRobert Mustacchi 28775eba5b6SRobert Mustacchi /** 28875eba5b6SRobert Mustacchi * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface 28975eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 29075eba5b6SRobert Mustacchi * @buffer: pointer to the host interface 29175eba5b6SRobert Mustacchi * @length: size of the buffer 29275eba5b6SRobert Mustacchi * 29375eba5b6SRobert Mustacchi * Writes the DHCP information to the host interface. 29475eba5b6SRobert Mustacchi **/ 29575eba5b6SRobert Mustacchi s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer, 29675eba5b6SRobert Mustacchi u16 length) 29775eba5b6SRobert Mustacchi { 29875eba5b6SRobert Mustacchi struct e1000_host_mng_command_header hdr; 29975eba5b6SRobert Mustacchi s32 ret_val; 30075eba5b6SRobert Mustacchi u32 hicr; 30175eba5b6SRobert Mustacchi 30275eba5b6SRobert Mustacchi DEBUGFUNC("e1000_mng_write_dhcp_info_generic"); 30375eba5b6SRobert Mustacchi 30475eba5b6SRobert Mustacchi hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; 30575eba5b6SRobert Mustacchi hdr.command_length = length; 30675eba5b6SRobert Mustacchi hdr.reserved1 = 0; 30775eba5b6SRobert Mustacchi hdr.reserved2 = 0; 30875eba5b6SRobert Mustacchi hdr.checksum = 0; 30975eba5b6SRobert Mustacchi 31075eba5b6SRobert Mustacchi /* Enable the host interface */ 31175eba5b6SRobert Mustacchi ret_val = e1000_mng_enable_host_if_generic(hw); 31275eba5b6SRobert Mustacchi if (ret_val) 31375eba5b6SRobert Mustacchi return ret_val; 31475eba5b6SRobert Mustacchi 31575eba5b6SRobert Mustacchi /* Populate the host interface with the contents of "buffer". */ 31675eba5b6SRobert Mustacchi ret_val = e1000_mng_host_if_write_generic(hw, buffer, length, 31775eba5b6SRobert Mustacchi sizeof(hdr), &(hdr.checksum)); 31875eba5b6SRobert Mustacchi if (ret_val) 31975eba5b6SRobert Mustacchi return ret_val; 32075eba5b6SRobert Mustacchi 32175eba5b6SRobert Mustacchi /* Write the manageability command header */ 32275eba5b6SRobert Mustacchi ret_val = e1000_mng_write_cmd_header_generic(hw, &hdr); 32375eba5b6SRobert Mustacchi if (ret_val) 32475eba5b6SRobert Mustacchi return ret_val; 32575eba5b6SRobert Mustacchi 32675eba5b6SRobert Mustacchi /* Tell the ARC a new command is pending. */ 32775eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 32875eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 32975eba5b6SRobert Mustacchi 33075eba5b6SRobert Mustacchi return E1000_SUCCESS; 33175eba5b6SRobert Mustacchi } 33275eba5b6SRobert Mustacchi 33375eba5b6SRobert Mustacchi /** 33475eba5b6SRobert Mustacchi * e1000_enable_mng_pass_thru - Check if management passthrough is needed 33575eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 33675eba5b6SRobert Mustacchi * 33775eba5b6SRobert Mustacchi * Verifies the hardware needs to leave interface enabled so that frames can 33875eba5b6SRobert Mustacchi * be directed to and from the management interface. 33975eba5b6SRobert Mustacchi **/ 34075eba5b6SRobert Mustacchi bool e1000_enable_mng_pass_thru(struct e1000_hw *hw) 34175eba5b6SRobert Mustacchi { 34275eba5b6SRobert Mustacchi u32 manc; 34375eba5b6SRobert Mustacchi u32 fwsm, factps; 34475eba5b6SRobert Mustacchi 34575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_enable_mng_pass_thru"); 34675eba5b6SRobert Mustacchi 34775eba5b6SRobert Mustacchi if (!hw->mac.asf_firmware_present) 34875eba5b6SRobert Mustacchi return FALSE; 34975eba5b6SRobert Mustacchi 35075eba5b6SRobert Mustacchi manc = E1000_READ_REG(hw, E1000_MANC); 35175eba5b6SRobert Mustacchi 35275eba5b6SRobert Mustacchi if (!(manc & E1000_MANC_RCV_TCO_EN)) 35375eba5b6SRobert Mustacchi return FALSE; 35475eba5b6SRobert Mustacchi 35575eba5b6SRobert Mustacchi if (hw->mac.has_fwsm) { 35675eba5b6SRobert Mustacchi fwsm = E1000_READ_REG(hw, E1000_FWSM); 35775eba5b6SRobert Mustacchi factps = E1000_READ_REG(hw, E1000_FACTPS); 35875eba5b6SRobert Mustacchi 35975eba5b6SRobert Mustacchi if (!(factps & E1000_FACTPS_MNGCG) && 36075eba5b6SRobert Mustacchi ((fwsm & E1000_FWSM_MODE_MASK) == 36175eba5b6SRobert Mustacchi (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) 36275eba5b6SRobert Mustacchi return TRUE; 36375eba5b6SRobert Mustacchi } else if ((hw->mac.type == e1000_82574) || 36475eba5b6SRobert Mustacchi (hw->mac.type == e1000_82583)) { 36575eba5b6SRobert Mustacchi u16 data; 366c124a83eSRobert Mustacchi s32 ret_val; 36775eba5b6SRobert Mustacchi 36875eba5b6SRobert Mustacchi factps = E1000_READ_REG(hw, E1000_FACTPS); 369c124a83eSRobert Mustacchi ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); 370c124a83eSRobert Mustacchi if (ret_val) 371c124a83eSRobert Mustacchi return FALSE; 37275eba5b6SRobert Mustacchi 37375eba5b6SRobert Mustacchi if (!(factps & E1000_FACTPS_MNGCG) && 37475eba5b6SRobert Mustacchi ((data & E1000_NVM_INIT_CTRL2_MNGM) == 37575eba5b6SRobert Mustacchi (e1000_mng_mode_pt << 13))) 37675eba5b6SRobert Mustacchi return TRUE; 37775eba5b6SRobert Mustacchi } else if ((manc & E1000_MANC_SMBUS_EN) && 37875eba5b6SRobert Mustacchi !(manc & E1000_MANC_ASF_EN)) { 37975eba5b6SRobert Mustacchi return TRUE; 38075eba5b6SRobert Mustacchi } 38175eba5b6SRobert Mustacchi 38275eba5b6SRobert Mustacchi return FALSE; 38375eba5b6SRobert Mustacchi } 38475eba5b6SRobert Mustacchi 38575eba5b6SRobert Mustacchi /** 38675eba5b6SRobert Mustacchi * e1000_host_interface_command - Writes buffer to host interface 38775eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 38875eba5b6SRobert Mustacchi * @buffer: contains a command to write 38975eba5b6SRobert Mustacchi * @length: the byte length of the buffer, must be multiple of 4 bytes 39075eba5b6SRobert Mustacchi * 39175eba5b6SRobert Mustacchi * Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS 39275eba5b6SRobert Mustacchi * else returns E1000_ERR_HOST_INTERFACE_COMMAND. 39375eba5b6SRobert Mustacchi **/ 39475eba5b6SRobert Mustacchi s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length) 39575eba5b6SRobert Mustacchi { 39675eba5b6SRobert Mustacchi u32 hicr, i; 39775eba5b6SRobert Mustacchi 39875eba5b6SRobert Mustacchi DEBUGFUNC("e1000_host_interface_command"); 39975eba5b6SRobert Mustacchi 40075eba5b6SRobert Mustacchi if (!(hw->mac.arc_subsystem_valid)) { 40175eba5b6SRobert Mustacchi DEBUGOUT("Hardware doesn't support host interface command.\n"); 40275eba5b6SRobert Mustacchi return E1000_SUCCESS; 40375eba5b6SRobert Mustacchi } 40475eba5b6SRobert Mustacchi 40575eba5b6SRobert Mustacchi if (!hw->mac.asf_firmware_present) { 40675eba5b6SRobert Mustacchi DEBUGOUT("Firmware is not present.\n"); 40775eba5b6SRobert Mustacchi return E1000_SUCCESS; 40875eba5b6SRobert Mustacchi } 40975eba5b6SRobert Mustacchi 41075eba5b6SRobert Mustacchi if (length == 0 || length & 0x3 || 41175eba5b6SRobert Mustacchi length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) { 41275eba5b6SRobert Mustacchi DEBUGOUT("Buffer length failure.\n"); 41375eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 41475eba5b6SRobert Mustacchi } 41575eba5b6SRobert Mustacchi 41675eba5b6SRobert Mustacchi /* Check that the host interface is enabled. */ 41775eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 41875eba5b6SRobert Mustacchi if (!(hicr & E1000_HICR_EN)) { 41975eba5b6SRobert Mustacchi DEBUGOUT("E1000_HOST_EN bit disabled.\n"); 42075eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 42175eba5b6SRobert Mustacchi } 42275eba5b6SRobert Mustacchi 42375eba5b6SRobert Mustacchi /* Calculate length in DWORDs */ 42475eba5b6SRobert Mustacchi length >>= 2; 42575eba5b6SRobert Mustacchi 42675eba5b6SRobert Mustacchi /* The device driver writes the relevant command block 42775eba5b6SRobert Mustacchi * into the ram area. 42875eba5b6SRobert Mustacchi */ 42975eba5b6SRobert Mustacchi for (i = 0; i < length; i++) 43075eba5b6SRobert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i, 43175eba5b6SRobert Mustacchi *((u32 *)buffer + i)); 43275eba5b6SRobert Mustacchi 43375eba5b6SRobert Mustacchi /* Setting this bit tells the ARC that a new command is pending. */ 43475eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 43575eba5b6SRobert Mustacchi 43675eba5b6SRobert Mustacchi for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { 43775eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 43875eba5b6SRobert Mustacchi if (!(hicr & E1000_HICR_C)) 43975eba5b6SRobert Mustacchi break; 44075eba5b6SRobert Mustacchi msec_delay(1); 44175eba5b6SRobert Mustacchi } 44275eba5b6SRobert Mustacchi 44375eba5b6SRobert Mustacchi /* Check command successful completion. */ 44475eba5b6SRobert Mustacchi if (i == E1000_HI_COMMAND_TIMEOUT || 44575eba5b6SRobert Mustacchi (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) { 44675eba5b6SRobert Mustacchi DEBUGOUT("Command has failed with no status valid.\n"); 44775eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 44875eba5b6SRobert Mustacchi } 44975eba5b6SRobert Mustacchi 45075eba5b6SRobert Mustacchi for (i = 0; i < length; i++) 45175eba5b6SRobert Mustacchi *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, 45275eba5b6SRobert Mustacchi E1000_HOST_IF, 45375eba5b6SRobert Mustacchi i); 45475eba5b6SRobert Mustacchi 45575eba5b6SRobert Mustacchi return E1000_SUCCESS; 45675eba5b6SRobert Mustacchi } 45775eba5b6SRobert Mustacchi /** 45875eba5b6SRobert Mustacchi * e1000_load_firmware - Writes proxy FW code buffer to host interface 45975eba5b6SRobert Mustacchi * and execute. 46075eba5b6SRobert Mustacchi * @hw: pointer to the HW structure 46175eba5b6SRobert Mustacchi * @buffer: contains a firmware to write 46275eba5b6SRobert Mustacchi * @length: the byte length of the buffer, must be multiple of 4 bytes 46375eba5b6SRobert Mustacchi * 46475eba5b6SRobert Mustacchi * Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled 46575eba5b6SRobert Mustacchi * in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND. 46675eba5b6SRobert Mustacchi **/ 46775eba5b6SRobert Mustacchi s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length) 46875eba5b6SRobert Mustacchi { 46975eba5b6SRobert Mustacchi u32 hicr, hibba, fwsm, icr, i; 47075eba5b6SRobert Mustacchi 47175eba5b6SRobert Mustacchi DEBUGFUNC("e1000_load_firmware"); 47275eba5b6SRobert Mustacchi 47375eba5b6SRobert Mustacchi if (hw->mac.type < e1000_i210) { 47475eba5b6SRobert Mustacchi DEBUGOUT("Hardware doesn't support loading FW by the driver\n"); 47575eba5b6SRobert Mustacchi return -E1000_ERR_CONFIG; 47675eba5b6SRobert Mustacchi } 47775eba5b6SRobert Mustacchi 47875eba5b6SRobert Mustacchi /* Check that the host interface is enabled. */ 47975eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 48075eba5b6SRobert Mustacchi if (!(hicr & E1000_HICR_EN)) { 48175eba5b6SRobert Mustacchi DEBUGOUT("E1000_HOST_EN bit disabled.\n"); 48275eba5b6SRobert Mustacchi return -E1000_ERR_CONFIG; 48375eba5b6SRobert Mustacchi } 48475eba5b6SRobert Mustacchi if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) { 48575eba5b6SRobert Mustacchi DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n"); 48675eba5b6SRobert Mustacchi return -E1000_ERR_CONFIG; 48775eba5b6SRobert Mustacchi } 48875eba5b6SRobert Mustacchi 48975eba5b6SRobert Mustacchi if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) { 49075eba5b6SRobert Mustacchi DEBUGOUT("Buffer length failure.\n"); 49175eba5b6SRobert Mustacchi return -E1000_ERR_INVALID_ARGUMENT; 49275eba5b6SRobert Mustacchi } 49375eba5b6SRobert Mustacchi 49475eba5b6SRobert Mustacchi /* Clear notification from ROM-FW by reading ICR register */ 49575eba5b6SRobert Mustacchi icr = E1000_READ_REG(hw, E1000_ICR_V2); 49675eba5b6SRobert Mustacchi 49775eba5b6SRobert Mustacchi /* Reset ROM-FW */ 49875eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 49975eba5b6SRobert Mustacchi hicr |= E1000_HICR_FW_RESET_ENABLE; 50075eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr); 50175eba5b6SRobert Mustacchi hicr |= E1000_HICR_FW_RESET; 50275eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr); 50375eba5b6SRobert Mustacchi E1000_WRITE_FLUSH(hw); 50475eba5b6SRobert Mustacchi 50575eba5b6SRobert Mustacchi /* Wait till MAC notifies about its readiness after ROM-FW reset */ 50675eba5b6SRobert Mustacchi for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) { 50775eba5b6SRobert Mustacchi icr = E1000_READ_REG(hw, E1000_ICR_V2); 50875eba5b6SRobert Mustacchi if (icr & E1000_ICR_MNG) 50975eba5b6SRobert Mustacchi break; 51075eba5b6SRobert Mustacchi msec_delay(1); 51175eba5b6SRobert Mustacchi } 51275eba5b6SRobert Mustacchi 51375eba5b6SRobert Mustacchi /* Check for timeout */ 51475eba5b6SRobert Mustacchi if (i == E1000_HI_COMMAND_TIMEOUT) { 51575eba5b6SRobert Mustacchi DEBUGOUT("FW reset failed.\n"); 51675eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 51775eba5b6SRobert Mustacchi } 51875eba5b6SRobert Mustacchi 51975eba5b6SRobert Mustacchi /* Wait till MAC is ready to accept new FW code */ 52075eba5b6SRobert Mustacchi for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { 52175eba5b6SRobert Mustacchi fwsm = E1000_READ_REG(hw, E1000_FWSM); 52275eba5b6SRobert Mustacchi if ((fwsm & E1000_FWSM_FW_VALID) && 52375eba5b6SRobert Mustacchi ((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT == 52475eba5b6SRobert Mustacchi E1000_FWSM_HI_EN_ONLY_MODE)) 52575eba5b6SRobert Mustacchi break; 52675eba5b6SRobert Mustacchi msec_delay(1); 52775eba5b6SRobert Mustacchi } 52875eba5b6SRobert Mustacchi 52975eba5b6SRobert Mustacchi /* Check for timeout */ 53075eba5b6SRobert Mustacchi if (i == E1000_HI_COMMAND_TIMEOUT) { 53175eba5b6SRobert Mustacchi DEBUGOUT("FW reset failed.\n"); 53275eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 53375eba5b6SRobert Mustacchi } 53475eba5b6SRobert Mustacchi 53575eba5b6SRobert Mustacchi /* Calculate length in DWORDs */ 53675eba5b6SRobert Mustacchi length >>= 2; 53775eba5b6SRobert Mustacchi 53875eba5b6SRobert Mustacchi /* The device driver writes the relevant FW code block 53975eba5b6SRobert Mustacchi * into the ram area in DWORDs via 1kB ram addressing window. 54075eba5b6SRobert Mustacchi */ 54175eba5b6SRobert Mustacchi for (i = 0; i < length; i++) { 54275eba5b6SRobert Mustacchi if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) { 54375eba5b6SRobert Mustacchi /* Point to correct 1kB ram window */ 54475eba5b6SRobert Mustacchi hibba = E1000_HI_FW_BASE_ADDRESS + 54575eba5b6SRobert Mustacchi ((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) * 54675eba5b6SRobert Mustacchi (i / E1000_HI_FW_BLOCK_DWORD_LENGTH)); 54775eba5b6SRobert Mustacchi 54875eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_HIBBA, hibba); 54975eba5b6SRobert Mustacchi } 55075eba5b6SRobert Mustacchi 55175eba5b6SRobert Mustacchi E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, 55275eba5b6SRobert Mustacchi i % E1000_HI_FW_BLOCK_DWORD_LENGTH, 55375eba5b6SRobert Mustacchi *((u32 *)buffer + i)); 55475eba5b6SRobert Mustacchi } 55575eba5b6SRobert Mustacchi 55675eba5b6SRobert Mustacchi /* Setting this bit tells the ARC that a new FW is ready to execute. */ 55775eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 55875eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C); 55975eba5b6SRobert Mustacchi 56075eba5b6SRobert Mustacchi for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) { 56175eba5b6SRobert Mustacchi hicr = E1000_READ_REG(hw, E1000_HICR); 56275eba5b6SRobert Mustacchi if (!(hicr & E1000_HICR_C)) 56375eba5b6SRobert Mustacchi break; 56475eba5b6SRobert Mustacchi msec_delay(1); 56575eba5b6SRobert Mustacchi } 56675eba5b6SRobert Mustacchi 56775eba5b6SRobert Mustacchi /* Check for successful FW start. */ 56875eba5b6SRobert Mustacchi if (i == E1000_HI_COMMAND_TIMEOUT) { 56975eba5b6SRobert Mustacchi DEBUGOUT("New FW did not start within timeout period.\n"); 57075eba5b6SRobert Mustacchi return -E1000_ERR_HOST_INTERFACE_COMMAND; 57175eba5b6SRobert Mustacchi } 57275eba5b6SRobert Mustacchi 57375eba5b6SRobert Mustacchi return E1000_SUCCESS; 57475eba5b6SRobert Mustacchi } 57575eba5b6SRobert Mustacchi 57675eba5b6SRobert Mustacchi 577