19c80d176SSepherosa Ziehau /******************************************************************************
29c80d176SSepherosa Ziehau
3*01a55482SSepherosa Ziehau Copyright (c) 2001-2019, Intel Corporation
49c80d176SSepherosa Ziehau All rights reserved.
59c80d176SSepherosa Ziehau
69c80d176SSepherosa Ziehau Redistribution and use in source and binary forms, with or without
79c80d176SSepherosa Ziehau modification, are permitted provided that the following conditions are met:
89c80d176SSepherosa Ziehau
99c80d176SSepherosa Ziehau 1. Redistributions of source code must retain the above copyright notice,
109c80d176SSepherosa Ziehau this list of conditions and the following disclaimer.
119c80d176SSepherosa Ziehau
129c80d176SSepherosa Ziehau 2. Redistributions in binary form must reproduce the above copyright
139c80d176SSepherosa Ziehau notice, this list of conditions and the following disclaimer in the
149c80d176SSepherosa Ziehau documentation and/or other materials provided with the distribution.
159c80d176SSepherosa Ziehau
169c80d176SSepherosa Ziehau 3. Neither the name of the Intel Corporation nor the names of its
179c80d176SSepherosa Ziehau contributors may be used to endorse or promote products derived from
189c80d176SSepherosa Ziehau this software without specific prior written permission.
199c80d176SSepherosa Ziehau
209c80d176SSepherosa Ziehau THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
219c80d176SSepherosa Ziehau AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229c80d176SSepherosa Ziehau IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239c80d176SSepherosa Ziehau ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
249c80d176SSepherosa Ziehau LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
259c80d176SSepherosa Ziehau CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
269c80d176SSepherosa Ziehau SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
279c80d176SSepherosa Ziehau INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
289c80d176SSepherosa Ziehau CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
299c80d176SSepherosa Ziehau ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
309c80d176SSepherosa Ziehau POSSIBILITY OF SUCH DAMAGE.
319c80d176SSepherosa Ziehau
329c80d176SSepherosa Ziehau ******************************************************************************/
3374dc3754SSepherosa Ziehau /*$FreeBSD$*/
349c80d176SSepherosa Ziehau
359c80d176SSepherosa Ziehau #include "e1000_api.h"
36*01a55482SSepherosa Ziehau #include "e1000_manage.h"
37*01a55482SSepherosa Ziehau
389c80d176SSepherosa Ziehau /**
399c80d176SSepherosa Ziehau * e1000_calculate_checksum - Calculate checksum for buffer
409c80d176SSepherosa Ziehau * @buffer: pointer to EEPROM
419c80d176SSepherosa Ziehau * @length: size of EEPROM to calculate a checksum for
429c80d176SSepherosa Ziehau *
439c80d176SSepherosa Ziehau * Calculates the checksum for some buffer on a specified length. The
449c80d176SSepherosa Ziehau * checksum calculated is returned.
459c80d176SSepherosa Ziehau **/
e1000_calculate_checksum(u8 * buffer,u32 length)4665aebe9fSSepherosa Ziehau u8 e1000_calculate_checksum(u8 *buffer, u32 length)
479c80d176SSepherosa Ziehau {
489c80d176SSepherosa Ziehau u32 i;
499c80d176SSepherosa Ziehau u8 sum = 0;
509c80d176SSepherosa Ziehau
519c80d176SSepherosa Ziehau DEBUGFUNC("e1000_calculate_checksum");
529c80d176SSepherosa Ziehau
539c80d176SSepherosa Ziehau if (!buffer)
549c80d176SSepherosa Ziehau return 0;
559c80d176SSepherosa Ziehau
569c80d176SSepherosa Ziehau for (i = 0; i < length; i++)
579c80d176SSepherosa Ziehau sum += buffer[i];
589c80d176SSepherosa Ziehau
599c80d176SSepherosa Ziehau return (u8) (0 - sum);
609c80d176SSepherosa Ziehau }
619c80d176SSepherosa Ziehau
629c80d176SSepherosa Ziehau /**
639c80d176SSepherosa Ziehau * e1000_mng_enable_host_if_generic - Checks host interface is enabled
649c80d176SSepherosa Ziehau * @hw: pointer to the HW structure
659c80d176SSepherosa Ziehau *
669c80d176SSepherosa Ziehau * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
679c80d176SSepherosa Ziehau *
689c80d176SSepherosa Ziehau * This function checks whether the HOST IF is enabled for command operation
699c80d176SSepherosa Ziehau * and also checks whether the previous command is completed. It busy waits
709c80d176SSepherosa Ziehau * in case of previous command is not completed.
719c80d176SSepherosa Ziehau **/
e1000_mng_enable_host_if_generic(struct e1000_hw * hw)729c80d176SSepherosa Ziehau s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
739c80d176SSepherosa Ziehau {
749c80d176SSepherosa Ziehau u32 hicr;
759c80d176SSepherosa Ziehau u8 i;
769c80d176SSepherosa Ziehau
779c80d176SSepherosa Ziehau DEBUGFUNC("e1000_mng_enable_host_if_generic");
789c80d176SSepherosa Ziehau
794be59a01SSepherosa Ziehau if (!hw->mac.arc_subsystem_valid) {
806a5a645eSSepherosa Ziehau DEBUGOUT("ARC subsystem not valid.\n");
814be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
826a5a645eSSepherosa Ziehau }
836a5a645eSSepherosa Ziehau
849c80d176SSepherosa Ziehau /* Check that the host interface is enabled. */
859c80d176SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
864be59a01SSepherosa Ziehau if (!(hicr & E1000_HICR_EN)) {
879c80d176SSepherosa Ziehau DEBUGOUT("E1000_HOST_EN bit disabled.\n");
884be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
899c80d176SSepherosa Ziehau }
909c80d176SSepherosa Ziehau /* check the previous command is completed */
919c80d176SSepherosa Ziehau for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
929c80d176SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
939c80d176SSepherosa Ziehau if (!(hicr & E1000_HICR_C))
949c80d176SSepherosa Ziehau break;
959c80d176SSepherosa Ziehau msec_delay_irq(1);
969c80d176SSepherosa Ziehau }
979c80d176SSepherosa Ziehau
989c80d176SSepherosa Ziehau if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
999c80d176SSepherosa Ziehau DEBUGOUT("Previous command timeout failed .\n");
1004be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
1019c80d176SSepherosa Ziehau }
1029c80d176SSepherosa Ziehau
1034be59a01SSepherosa Ziehau return E1000_SUCCESS;
1049c80d176SSepherosa Ziehau }
1059c80d176SSepherosa Ziehau
1069c80d176SSepherosa Ziehau /**
1079c80d176SSepherosa Ziehau * e1000_check_mng_mode_generic - Generic check management mode
1089c80d176SSepherosa Ziehau * @hw: pointer to the HW structure
1099c80d176SSepherosa Ziehau *
1109c80d176SSepherosa Ziehau * Reads the firmware semaphore register and returns TRUE (>0) if
1119c80d176SSepherosa Ziehau * manageability is enabled, else FALSE (0).
1129c80d176SSepherosa Ziehau **/
e1000_check_mng_mode_generic(struct e1000_hw * hw)1139c80d176SSepherosa Ziehau bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
1149c80d176SSepherosa Ziehau {
1156a5a645eSSepherosa Ziehau u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
1169c80d176SSepherosa Ziehau
1179c80d176SSepherosa Ziehau DEBUGFUNC("e1000_check_mng_mode_generic");
1189c80d176SSepherosa Ziehau
1199c80d176SSepherosa Ziehau
1209c80d176SSepherosa Ziehau return (fwsm & E1000_FWSM_MODE_MASK) ==
1219c80d176SSepherosa Ziehau (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
1229c80d176SSepherosa Ziehau }
1239c80d176SSepherosa Ziehau
1249c80d176SSepherosa Ziehau /**
1256a5a645eSSepherosa Ziehau * e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
1269c80d176SSepherosa Ziehau * @hw: pointer to the HW structure
1279c80d176SSepherosa Ziehau *
1289c80d176SSepherosa Ziehau * Enables packet filtering on transmit packets if manageability is enabled
1299c80d176SSepherosa Ziehau * and host interface is enabled.
1309c80d176SSepherosa Ziehau **/
e1000_enable_tx_pkt_filtering_generic(struct e1000_hw * hw)1319c80d176SSepherosa Ziehau bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
1329c80d176SSepherosa Ziehau {
1339c80d176SSepherosa Ziehau struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
1349c80d176SSepherosa Ziehau u32 *buffer = (u32 *)&hw->mng_cookie;
1359c80d176SSepherosa Ziehau u32 offset;
1369c80d176SSepherosa Ziehau s32 ret_val, hdr_csum, csum;
1379c80d176SSepherosa Ziehau u8 i, len;
1389c80d176SSepherosa Ziehau
1399c80d176SSepherosa Ziehau DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
1409c80d176SSepherosa Ziehau
1416a5a645eSSepherosa Ziehau hw->mac.tx_pkt_filtering = TRUE;
1426a5a645eSSepherosa Ziehau
1439c80d176SSepherosa Ziehau /* No manageability, no filtering */
1449c80d176SSepherosa Ziehau if (!hw->mac.ops.check_mng_mode(hw)) {
1456a5a645eSSepherosa Ziehau hw->mac.tx_pkt_filtering = FALSE;
1464be59a01SSepherosa Ziehau return hw->mac.tx_pkt_filtering;
1479c80d176SSepherosa Ziehau }
1489c80d176SSepherosa Ziehau
149379ebbe7SSepherosa Ziehau /* If we can't read from the host interface for whatever
1509c80d176SSepherosa Ziehau * reason, disable filtering.
1519c80d176SSepherosa Ziehau */
152379ebbe7SSepherosa Ziehau ret_val = e1000_mng_enable_host_if_generic(hw);
1539c80d176SSepherosa Ziehau if (ret_val != E1000_SUCCESS) {
1546a5a645eSSepherosa Ziehau hw->mac.tx_pkt_filtering = FALSE;
1554be59a01SSepherosa Ziehau return hw->mac.tx_pkt_filtering;
1569c80d176SSepherosa Ziehau }
1579c80d176SSepherosa Ziehau
1589c80d176SSepherosa Ziehau /* Read in the header. Length and offset are in dwords. */
1599c80d176SSepherosa Ziehau len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
1609c80d176SSepherosa Ziehau offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
1616a5a645eSSepherosa Ziehau for (i = 0; i < len; i++)
1626a5a645eSSepherosa Ziehau *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
1639c80d176SSepherosa Ziehau offset + i);
1649c80d176SSepherosa Ziehau hdr_csum = hdr->checksum;
1659c80d176SSepherosa Ziehau hdr->checksum = 0;
1669c80d176SSepherosa Ziehau csum = e1000_calculate_checksum((u8 *)hdr,
1679c80d176SSepherosa Ziehau E1000_MNG_DHCP_COOKIE_LENGTH);
168379ebbe7SSepherosa Ziehau /* If either the checksums or signature don't match, then
1699c80d176SSepherosa Ziehau * the cookie area isn't considered valid, in which case we
1709c80d176SSepherosa Ziehau * take the safe route of assuming Tx filtering is enabled.
1719c80d176SSepherosa Ziehau */
1726a5a645eSSepherosa Ziehau if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
1736a5a645eSSepherosa Ziehau hw->mac.tx_pkt_filtering = TRUE;
1746a5a645eSSepherosa Ziehau return hw->mac.tx_pkt_filtering;
1759c80d176SSepherosa Ziehau }
1769c80d176SSepherosa Ziehau
1774be59a01SSepherosa Ziehau /* Cookie area is valid, make the final check for filtering. */
1784be59a01SSepherosa Ziehau if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
1794be59a01SSepherosa Ziehau hw->mac.tx_pkt_filtering = FALSE;
1809c80d176SSepherosa Ziehau
1814be59a01SSepherosa Ziehau return hw->mac.tx_pkt_filtering;
1829c80d176SSepherosa Ziehau }
1839c80d176SSepherosa Ziehau
1849c80d176SSepherosa Ziehau /**
1859c80d176SSepherosa Ziehau * e1000_mng_write_cmd_header_generic - Writes manageability command header
1869c80d176SSepherosa Ziehau * @hw: pointer to the HW structure
1879c80d176SSepherosa Ziehau * @hdr: pointer to the host interface command header
1889c80d176SSepherosa Ziehau *
1899c80d176SSepherosa Ziehau * Writes the command header after does the checksum calculation.
1909c80d176SSepherosa Ziehau **/
e1000_mng_write_cmd_header_generic(struct e1000_hw * hw,struct e1000_host_mng_command_header * hdr)1919c80d176SSepherosa Ziehau s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
1929c80d176SSepherosa Ziehau struct e1000_host_mng_command_header *hdr)
1939c80d176SSepherosa Ziehau {
1949c80d176SSepherosa Ziehau u16 i, length = sizeof(struct e1000_host_mng_command_header);
1959c80d176SSepherosa Ziehau
1969c80d176SSepherosa Ziehau DEBUGFUNC("e1000_mng_write_cmd_header_generic");
1979c80d176SSepherosa Ziehau
1989c80d176SSepherosa Ziehau /* Write the whole command header structure with new checksum. */
1999c80d176SSepherosa Ziehau
2009c80d176SSepherosa Ziehau hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
2019c80d176SSepherosa Ziehau
2029c80d176SSepherosa Ziehau length >>= 2;
2039c80d176SSepherosa Ziehau /* Write the relevant command block into the ram area. */
2049c80d176SSepherosa Ziehau for (i = 0; i < length; i++) {
2059c80d176SSepherosa Ziehau E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
2069c80d176SSepherosa Ziehau *((u32 *) hdr + i));
2079c80d176SSepherosa Ziehau E1000_WRITE_FLUSH(hw);
2089c80d176SSepherosa Ziehau }
2099c80d176SSepherosa Ziehau
2109c80d176SSepherosa Ziehau return E1000_SUCCESS;
2119c80d176SSepherosa Ziehau }
2129c80d176SSepherosa Ziehau
2139c80d176SSepherosa Ziehau /**
2149c80d176SSepherosa Ziehau * e1000_mng_host_if_write_generic - Write to the manageability host interface
2159c80d176SSepherosa Ziehau * @hw: pointer to the HW structure
2169c80d176SSepherosa Ziehau * @buffer: pointer to the host interface buffer
2179c80d176SSepherosa Ziehau * @length: size of the buffer
2189c80d176SSepherosa Ziehau * @offset: location in the buffer to write to
2199c80d176SSepherosa Ziehau * @sum: sum of the data (not checksum)
2209c80d176SSepherosa Ziehau *
2219c80d176SSepherosa Ziehau * This function writes the buffer content at the offset given on the host if.
2229c80d176SSepherosa Ziehau * It also does alignment considerations to do the writes in most efficient
2239c80d176SSepherosa Ziehau * way. Also fills up the sum of the buffer in *buffer parameter.
2249c80d176SSepherosa Ziehau **/
e1000_mng_host_if_write_generic(struct e1000_hw * hw,u8 * buffer,u16 length,u16 offset,u8 * sum)2259c80d176SSepherosa Ziehau s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
2269c80d176SSepherosa Ziehau u16 length, u16 offset, u8 *sum)
2279c80d176SSepherosa Ziehau {
2289c80d176SSepherosa Ziehau u8 *tmp;
2299c80d176SSepherosa Ziehau u8 *bufptr = buffer;
2309c80d176SSepherosa Ziehau u32 data = 0;
2319c80d176SSepherosa Ziehau u16 remaining, i, j, prev_bytes;
2329c80d176SSepherosa Ziehau
2339c80d176SSepherosa Ziehau DEBUGFUNC("e1000_mng_host_if_write_generic");
2349c80d176SSepherosa Ziehau
2359c80d176SSepherosa Ziehau /* sum = only sum of the data and it is not checksum */
2369c80d176SSepherosa Ziehau
2374be59a01SSepherosa Ziehau if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH)
2384be59a01SSepherosa Ziehau return -E1000_ERR_PARAM;
2399c80d176SSepherosa Ziehau
2409c80d176SSepherosa Ziehau tmp = (u8 *)&data;
2419c80d176SSepherosa Ziehau prev_bytes = offset & 0x3;
2429c80d176SSepherosa Ziehau offset >>= 2;
2439c80d176SSepherosa Ziehau
2449c80d176SSepherosa Ziehau if (prev_bytes) {
2459c80d176SSepherosa Ziehau data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
2469c80d176SSepherosa Ziehau for (j = prev_bytes; j < sizeof(u32); j++) {
2479c80d176SSepherosa Ziehau *(tmp + j) = *bufptr++;
2489c80d176SSepherosa Ziehau *sum += *(tmp + j);
2499c80d176SSepherosa Ziehau }
2509c80d176SSepherosa Ziehau E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
2519c80d176SSepherosa Ziehau length -= j - prev_bytes;
2529c80d176SSepherosa Ziehau offset++;
2539c80d176SSepherosa Ziehau }
2549c80d176SSepherosa Ziehau
2559c80d176SSepherosa Ziehau remaining = length & 0x3;
2569c80d176SSepherosa Ziehau length -= remaining;
2579c80d176SSepherosa Ziehau
2589c80d176SSepherosa Ziehau /* Calculate length in DWORDs */
2599c80d176SSepherosa Ziehau length >>= 2;
2609c80d176SSepherosa Ziehau
261379ebbe7SSepherosa Ziehau /* The device driver writes the relevant command block into the
2629c80d176SSepherosa Ziehau * ram area.
2639c80d176SSepherosa Ziehau */
2649c80d176SSepherosa Ziehau for (i = 0; i < length; i++) {
2659c80d176SSepherosa Ziehau for (j = 0; j < sizeof(u32); j++) {
2669c80d176SSepherosa Ziehau *(tmp + j) = *bufptr++;
2679c80d176SSepherosa Ziehau *sum += *(tmp + j);
2689c80d176SSepherosa Ziehau }
2699c80d176SSepherosa Ziehau
2709c80d176SSepherosa Ziehau E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
2719c80d176SSepherosa Ziehau data);
2729c80d176SSepherosa Ziehau }
2739c80d176SSepherosa Ziehau if (remaining) {
2749c80d176SSepherosa Ziehau for (j = 0; j < sizeof(u32); j++) {
2759c80d176SSepherosa Ziehau if (j < remaining)
2769c80d176SSepherosa Ziehau *(tmp + j) = *bufptr++;
2779c80d176SSepherosa Ziehau else
2789c80d176SSepherosa Ziehau *(tmp + j) = 0;
2799c80d176SSepherosa Ziehau
2809c80d176SSepherosa Ziehau *sum += *(tmp + j);
2819c80d176SSepherosa Ziehau }
2824be59a01SSepherosa Ziehau E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
2834be59a01SSepherosa Ziehau data);
2849c80d176SSepherosa Ziehau }
2859c80d176SSepherosa Ziehau
2864be59a01SSepherosa Ziehau return E1000_SUCCESS;
2874be59a01SSepherosa Ziehau }
2884be59a01SSepherosa Ziehau
2894be59a01SSepherosa Ziehau /**
2904be59a01SSepherosa Ziehau * e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
2914be59a01SSepherosa Ziehau * @hw: pointer to the HW structure
2924be59a01SSepherosa Ziehau * @buffer: pointer to the host interface
2934be59a01SSepherosa Ziehau * @length: size of the buffer
2944be59a01SSepherosa Ziehau *
2954be59a01SSepherosa Ziehau * Writes the DHCP information to the host interface.
2964be59a01SSepherosa Ziehau **/
e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw,u8 * buffer,u16 length)2974be59a01SSepherosa Ziehau s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
2984be59a01SSepherosa Ziehau u16 length)
2994be59a01SSepherosa Ziehau {
3004be59a01SSepherosa Ziehau struct e1000_host_mng_command_header hdr;
3014be59a01SSepherosa Ziehau s32 ret_val;
3024be59a01SSepherosa Ziehau u32 hicr;
3034be59a01SSepherosa Ziehau
3044be59a01SSepherosa Ziehau DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
3054be59a01SSepherosa Ziehau
3064be59a01SSepherosa Ziehau hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
3074be59a01SSepherosa Ziehau hdr.command_length = length;
3084be59a01SSepherosa Ziehau hdr.reserved1 = 0;
3094be59a01SSepherosa Ziehau hdr.reserved2 = 0;
3104be59a01SSepherosa Ziehau hdr.checksum = 0;
3114be59a01SSepherosa Ziehau
3124be59a01SSepherosa Ziehau /* Enable the host interface */
313379ebbe7SSepherosa Ziehau ret_val = e1000_mng_enable_host_if_generic(hw);
3144be59a01SSepherosa Ziehau if (ret_val)
3159c80d176SSepherosa Ziehau return ret_val;
3164be59a01SSepherosa Ziehau
3174be59a01SSepherosa Ziehau /* Populate the host interface with the contents of "buffer". */
318379ebbe7SSepherosa Ziehau ret_val = e1000_mng_host_if_write_generic(hw, buffer, length,
3194be59a01SSepherosa Ziehau sizeof(hdr), &(hdr.checksum));
3204be59a01SSepherosa Ziehau if (ret_val)
3214be59a01SSepherosa Ziehau return ret_val;
3224be59a01SSepherosa Ziehau
3234be59a01SSepherosa Ziehau /* Write the manageability command header */
324379ebbe7SSepherosa Ziehau ret_val = e1000_mng_write_cmd_header_generic(hw, &hdr);
3254be59a01SSepherosa Ziehau if (ret_val)
3264be59a01SSepherosa Ziehau return ret_val;
3274be59a01SSepherosa Ziehau
3284be59a01SSepherosa Ziehau /* Tell the ARC a new command is pending. */
3294be59a01SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
3304be59a01SSepherosa Ziehau E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
3314be59a01SSepherosa Ziehau
3324be59a01SSepherosa Ziehau return E1000_SUCCESS;
3339c80d176SSepherosa Ziehau }
3349c80d176SSepherosa Ziehau
3359c80d176SSepherosa Ziehau /**
3366a5a645eSSepherosa Ziehau * e1000_enable_mng_pass_thru - Check if management passthrough is needed
3379c80d176SSepherosa Ziehau * @hw: pointer to the HW structure
3389c80d176SSepherosa Ziehau *
3396a5a645eSSepherosa Ziehau * Verifies the hardware needs to leave interface enabled so that frames can
3406a5a645eSSepherosa Ziehau * be directed to and from the management interface.
3419c80d176SSepherosa Ziehau **/
e1000_enable_mng_pass_thru(struct e1000_hw * hw)3429c80d176SSepherosa Ziehau bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
3439c80d176SSepherosa Ziehau {
3449c80d176SSepherosa Ziehau u32 manc;
3459c80d176SSepherosa Ziehau u32 fwsm, factps;
3469c80d176SSepherosa Ziehau
3479c80d176SSepherosa Ziehau DEBUGFUNC("e1000_enable_mng_pass_thru");
3489c80d176SSepherosa Ziehau
3499c80d176SSepherosa Ziehau if (!hw->mac.asf_firmware_present)
3504be59a01SSepherosa Ziehau return FALSE;
3519c80d176SSepherosa Ziehau
3529c80d176SSepherosa Ziehau manc = E1000_READ_REG(hw, E1000_MANC);
3539c80d176SSepherosa Ziehau
3546a5a645eSSepherosa Ziehau if (!(manc & E1000_MANC_RCV_TCO_EN))
3554be59a01SSepherosa Ziehau return FALSE;
3569c80d176SSepherosa Ziehau
3576a5a645eSSepherosa Ziehau if (hw->mac.has_fwsm) {
3589c80d176SSepherosa Ziehau fwsm = E1000_READ_REG(hw, E1000_FWSM);
3599c80d176SSepherosa Ziehau factps = E1000_READ_REG(hw, E1000_FACTPS);
3609c80d176SSepherosa Ziehau
3619c80d176SSepherosa Ziehau if (!(factps & E1000_FACTPS_MNGCG) &&
3629c80d176SSepherosa Ziehau ((fwsm & E1000_FWSM_MODE_MASK) ==
3634be59a01SSepherosa Ziehau (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)))
3644be59a01SSepherosa Ziehau return TRUE;
3656a5a645eSSepherosa Ziehau } else if ((hw->mac.type == e1000_82574) ||
3666a5a645eSSepherosa Ziehau (hw->mac.type == e1000_82583)) {
3676a5a645eSSepherosa Ziehau u16 data;
3684765c386SMichael Neumann s32 ret_val;
3696a5a645eSSepherosa Ziehau
3706a5a645eSSepherosa Ziehau factps = E1000_READ_REG(hw, E1000_FACTPS);
3714765c386SMichael Neumann ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
3724765c386SMichael Neumann if (ret_val)
3734765c386SMichael Neumann return FALSE;
3746a5a645eSSepherosa Ziehau
3756a5a645eSSepherosa Ziehau if (!(factps & E1000_FACTPS_MNGCG) &&
3766a5a645eSSepherosa Ziehau ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
3774be59a01SSepherosa Ziehau (e1000_mng_mode_pt << 13)))
3784be59a01SSepherosa Ziehau return TRUE;
3796a5a645eSSepherosa Ziehau } else if ((manc & E1000_MANC_SMBUS_EN) &&
3806a5a645eSSepherosa Ziehau !(manc & E1000_MANC_ASF_EN)) {
3814be59a01SSepherosa Ziehau return TRUE;
3829c80d176SSepherosa Ziehau }
3839c80d176SSepherosa Ziehau
3844be59a01SSepherosa Ziehau return FALSE;
3859c80d176SSepherosa Ziehau }
3869c80d176SSepherosa Ziehau
38762583d18SSepherosa Ziehau /**
38862583d18SSepherosa Ziehau * e1000_host_interface_command - Writes buffer to host interface
38962583d18SSepherosa Ziehau * @hw: pointer to the HW structure
39062583d18SSepherosa Ziehau * @buffer: contains a command to write
39162583d18SSepherosa Ziehau * @length: the byte length of the buffer, must be multiple of 4 bytes
39262583d18SSepherosa Ziehau *
39362583d18SSepherosa Ziehau * Writes a buffer to the Host Interface. Upon success, returns E1000_SUCCESS
39462583d18SSepherosa Ziehau * else returns E1000_ERR_HOST_INTERFACE_COMMAND.
39562583d18SSepherosa Ziehau **/
e1000_host_interface_command(struct e1000_hw * hw,u8 * buffer,u32 length)39662583d18SSepherosa Ziehau s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
39762583d18SSepherosa Ziehau {
39862583d18SSepherosa Ziehau u32 hicr, i;
39962583d18SSepherosa Ziehau
40062583d18SSepherosa Ziehau DEBUGFUNC("e1000_host_interface_command");
40162583d18SSepherosa Ziehau
40262583d18SSepherosa Ziehau if (!(hw->mac.arc_subsystem_valid)) {
40362583d18SSepherosa Ziehau DEBUGOUT("Hardware doesn't support host interface command.\n");
4044be59a01SSepherosa Ziehau return E1000_SUCCESS;
40562583d18SSepherosa Ziehau }
40662583d18SSepherosa Ziehau
40762583d18SSepherosa Ziehau if (!hw->mac.asf_firmware_present) {
40862583d18SSepherosa Ziehau DEBUGOUT("Firmware is not present.\n");
4094be59a01SSepherosa Ziehau return E1000_SUCCESS;
41062583d18SSepherosa Ziehau }
41162583d18SSepherosa Ziehau
41262583d18SSepherosa Ziehau if (length == 0 || length & 0x3 ||
41362583d18SSepherosa Ziehau length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
41462583d18SSepherosa Ziehau DEBUGOUT("Buffer length failure.\n");
4154be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
41662583d18SSepherosa Ziehau }
41762583d18SSepherosa Ziehau
41862583d18SSepherosa Ziehau /* Check that the host interface is enabled. */
41962583d18SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
4204be59a01SSepherosa Ziehau if (!(hicr & E1000_HICR_EN)) {
42162583d18SSepherosa Ziehau DEBUGOUT("E1000_HOST_EN bit disabled.\n");
4224be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
42362583d18SSepherosa Ziehau }
42462583d18SSepherosa Ziehau
42562583d18SSepherosa Ziehau /* Calculate length in DWORDs */
42662583d18SSepherosa Ziehau length >>= 2;
42762583d18SSepherosa Ziehau
428379ebbe7SSepherosa Ziehau /* The device driver writes the relevant command block
42962583d18SSepherosa Ziehau * into the ram area.
43062583d18SSepherosa Ziehau */
43162583d18SSepherosa Ziehau for (i = 0; i < length; i++)
4324be59a01SSepherosa Ziehau E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
43362583d18SSepherosa Ziehau *((u32 *)buffer + i));
43462583d18SSepherosa Ziehau
43562583d18SSepherosa Ziehau /* Setting this bit tells the ARC that a new command is pending. */
43662583d18SSepherosa Ziehau E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
43762583d18SSepherosa Ziehau
43862583d18SSepherosa Ziehau for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
43962583d18SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
44062583d18SSepherosa Ziehau if (!(hicr & E1000_HICR_C))
44162583d18SSepherosa Ziehau break;
44262583d18SSepherosa Ziehau msec_delay(1);
44362583d18SSepherosa Ziehau }
44462583d18SSepherosa Ziehau
44562583d18SSepherosa Ziehau /* Check command successful completion. */
44662583d18SSepherosa Ziehau if (i == E1000_HI_COMMAND_TIMEOUT ||
44762583d18SSepherosa Ziehau (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
44862583d18SSepherosa Ziehau DEBUGOUT("Command has failed with no status valid.\n");
4494be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
45062583d18SSepherosa Ziehau }
45162583d18SSepherosa Ziehau
45262583d18SSepherosa Ziehau for (i = 0; i < length; i++)
45362583d18SSepherosa Ziehau *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
45462583d18SSepherosa Ziehau E1000_HOST_IF,
45562583d18SSepherosa Ziehau i);
45662583d18SSepherosa Ziehau
4574be59a01SSepherosa Ziehau return E1000_SUCCESS;
45862583d18SSepherosa Ziehau }
4594be59a01SSepherosa Ziehau /**
4604be59a01SSepherosa Ziehau * e1000_load_firmware - Writes proxy FW code buffer to host interface
4614be59a01SSepherosa Ziehau * and execute.
4624be59a01SSepherosa Ziehau * @hw: pointer to the HW structure
4634be59a01SSepherosa Ziehau * @buffer: contains a firmware to write
4644be59a01SSepherosa Ziehau * @length: the byte length of the buffer, must be multiple of 4 bytes
4654be59a01SSepherosa Ziehau *
4664be59a01SSepherosa Ziehau * Upon success returns E1000_SUCCESS, returns E1000_ERR_CONFIG if not enabled
4674be59a01SSepherosa Ziehau * in HW else returns E1000_ERR_HOST_INTERFACE_COMMAND.
4684be59a01SSepherosa Ziehau **/
e1000_load_firmware(struct e1000_hw * hw,u8 * buffer,u32 length)4694be59a01SSepherosa Ziehau s32 e1000_load_firmware(struct e1000_hw *hw, u8 *buffer, u32 length)
4704be59a01SSepherosa Ziehau {
4714be59a01SSepherosa Ziehau u32 hicr, hibba, fwsm, icr, i;
4724be59a01SSepherosa Ziehau
4734be59a01SSepherosa Ziehau DEBUGFUNC("e1000_load_firmware");
4744be59a01SSepherosa Ziehau
4754be59a01SSepherosa Ziehau if (hw->mac.type < e1000_i210) {
4764be59a01SSepherosa Ziehau DEBUGOUT("Hardware doesn't support loading FW by the driver\n");
4774be59a01SSepherosa Ziehau return -E1000_ERR_CONFIG;
4784be59a01SSepherosa Ziehau }
4794be59a01SSepherosa Ziehau
4804be59a01SSepherosa Ziehau /* Check that the host interface is enabled. */
4814be59a01SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
4824be59a01SSepherosa Ziehau if (!(hicr & E1000_HICR_EN)) {
4834be59a01SSepherosa Ziehau DEBUGOUT("E1000_HOST_EN bit disabled.\n");
4844be59a01SSepherosa Ziehau return -E1000_ERR_CONFIG;
4854be59a01SSepherosa Ziehau }
4864be59a01SSepherosa Ziehau if (!(hicr & E1000_HICR_MEMORY_BASE_EN)) {
4874be59a01SSepherosa Ziehau DEBUGOUT("E1000_HICR_MEMORY_BASE_EN bit disabled.\n");
4884be59a01SSepherosa Ziehau return -E1000_ERR_CONFIG;
4894be59a01SSepherosa Ziehau }
4904be59a01SSepherosa Ziehau
4914be59a01SSepherosa Ziehau if (length == 0 || length & 0x3 || length > E1000_HI_FW_MAX_LENGTH) {
4924be59a01SSepherosa Ziehau DEBUGOUT("Buffer length failure.\n");
4934be59a01SSepherosa Ziehau return -E1000_ERR_INVALID_ARGUMENT;
4944be59a01SSepherosa Ziehau }
4954be59a01SSepherosa Ziehau
4964be59a01SSepherosa Ziehau /* Clear notification from ROM-FW by reading ICR register */
4974be59a01SSepherosa Ziehau icr = E1000_READ_REG(hw, E1000_ICR_V2);
4984be59a01SSepherosa Ziehau
4994be59a01SSepherosa Ziehau /* Reset ROM-FW */
5004be59a01SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
5014be59a01SSepherosa Ziehau hicr |= E1000_HICR_FW_RESET_ENABLE;
5024be59a01SSepherosa Ziehau E1000_WRITE_REG(hw, E1000_HICR, hicr);
5034be59a01SSepherosa Ziehau hicr |= E1000_HICR_FW_RESET;
5044be59a01SSepherosa Ziehau E1000_WRITE_REG(hw, E1000_HICR, hicr);
5054be59a01SSepherosa Ziehau E1000_WRITE_FLUSH(hw);
5064be59a01SSepherosa Ziehau
5074be59a01SSepherosa Ziehau /* Wait till MAC notifies about its readiness after ROM-FW reset */
5084be59a01SSepherosa Ziehau for (i = 0; i < (E1000_HI_COMMAND_TIMEOUT * 2); i++) {
5094be59a01SSepherosa Ziehau icr = E1000_READ_REG(hw, E1000_ICR_V2);
5104be59a01SSepherosa Ziehau if (icr & E1000_ICR_MNG)
5114be59a01SSepherosa Ziehau break;
5124be59a01SSepherosa Ziehau msec_delay(1);
5134be59a01SSepherosa Ziehau }
5144be59a01SSepherosa Ziehau
5154be59a01SSepherosa Ziehau /* Check for timeout */
5164be59a01SSepherosa Ziehau if (i == E1000_HI_COMMAND_TIMEOUT) {
5174be59a01SSepherosa Ziehau DEBUGOUT("FW reset failed.\n");
5184be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
5194be59a01SSepherosa Ziehau }
5204be59a01SSepherosa Ziehau
5214be59a01SSepherosa Ziehau /* Wait till MAC is ready to accept new FW code */
5224be59a01SSepherosa Ziehau for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
5234be59a01SSepherosa Ziehau fwsm = E1000_READ_REG(hw, E1000_FWSM);
5244be59a01SSepherosa Ziehau if ((fwsm & E1000_FWSM_FW_VALID) &&
5254be59a01SSepherosa Ziehau ((fwsm & E1000_FWSM_MODE_MASK) >> E1000_FWSM_MODE_SHIFT ==
5264be59a01SSepherosa Ziehau E1000_FWSM_HI_EN_ONLY_MODE))
5274be59a01SSepherosa Ziehau break;
5284be59a01SSepherosa Ziehau msec_delay(1);
5294be59a01SSepherosa Ziehau }
5304be59a01SSepherosa Ziehau
5314be59a01SSepherosa Ziehau /* Check for timeout */
5324be59a01SSepherosa Ziehau if (i == E1000_HI_COMMAND_TIMEOUT) {
5334be59a01SSepherosa Ziehau DEBUGOUT("FW reset failed.\n");
5344be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
5354be59a01SSepherosa Ziehau }
5364be59a01SSepherosa Ziehau
5374be59a01SSepherosa Ziehau /* Calculate length in DWORDs */
5384be59a01SSepherosa Ziehau length >>= 2;
5394be59a01SSepherosa Ziehau
540379ebbe7SSepherosa Ziehau /* The device driver writes the relevant FW code block
5414be59a01SSepherosa Ziehau * into the ram area in DWORDs via 1kB ram addressing window.
5424be59a01SSepherosa Ziehau */
5434be59a01SSepherosa Ziehau for (i = 0; i < length; i++) {
5444be59a01SSepherosa Ziehau if (!(i % E1000_HI_FW_BLOCK_DWORD_LENGTH)) {
5454be59a01SSepherosa Ziehau /* Point to correct 1kB ram window */
5464be59a01SSepherosa Ziehau hibba = E1000_HI_FW_BASE_ADDRESS +
5474be59a01SSepherosa Ziehau ((E1000_HI_FW_BLOCK_DWORD_LENGTH << 2) *
5484be59a01SSepherosa Ziehau (i / E1000_HI_FW_BLOCK_DWORD_LENGTH));
5494be59a01SSepherosa Ziehau
5504be59a01SSepherosa Ziehau E1000_WRITE_REG(hw, E1000_HIBBA, hibba);
5514be59a01SSepherosa Ziehau }
5524be59a01SSepherosa Ziehau
5534be59a01SSepherosa Ziehau E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
5544be59a01SSepherosa Ziehau i % E1000_HI_FW_BLOCK_DWORD_LENGTH,
5554be59a01SSepherosa Ziehau *((u32 *)buffer + i));
5564be59a01SSepherosa Ziehau }
5574be59a01SSepherosa Ziehau
5584be59a01SSepherosa Ziehau /* Setting this bit tells the ARC that a new FW is ready to execute. */
5594be59a01SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
5604be59a01SSepherosa Ziehau E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
5614be59a01SSepherosa Ziehau
5624be59a01SSepherosa Ziehau for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
5634be59a01SSepherosa Ziehau hicr = E1000_READ_REG(hw, E1000_HICR);
5644be59a01SSepherosa Ziehau if (!(hicr & E1000_HICR_C))
5654be59a01SSepherosa Ziehau break;
5664be59a01SSepherosa Ziehau msec_delay(1);
5674be59a01SSepherosa Ziehau }
5684be59a01SSepherosa Ziehau
5694be59a01SSepherosa Ziehau /* Check for successful FW start. */
5704be59a01SSepherosa Ziehau if (i == E1000_HI_COMMAND_TIMEOUT) {
5714be59a01SSepherosa Ziehau DEBUGOUT("New FW did not start within timeout period.\n");
5724be59a01SSepherosa Ziehau return -E1000_ERR_HOST_INTERFACE_COMMAND;
5734be59a01SSepherosa Ziehau }
5744be59a01SSepherosa Ziehau
5754be59a01SSepherosa Ziehau return E1000_SUCCESS;
5764be59a01SSepherosa Ziehau }
5774be59a01SSepherosa Ziehau
57862583d18SSepherosa Ziehau
579