The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/em/e1000_manage.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*******************************************************************************
    2 
    3   Copyright (c) 2001-2007, Intel Corporation 
    4   All rights reserved.
    5   
    6   Redistribution and use in source and binary forms, with or without 
    7   modification, are permitted provided that the following conditions are met:
    8   
    9    1. Redistributions of source code must retain the above copyright notice, 
   10       this list of conditions and the following disclaimer.
   11   
   12    2. Redistributions in binary form must reproduce the above copyright 
   13       notice, this list of conditions and the following disclaimer in the 
   14       documentation and/or other materials provided with the distribution.
   15   
   16    3. Neither the name of the Intel Corporation nor the names of its 
   17       contributors may be used to endorse or promote products derived from 
   18       this software without specific prior written permission.
   19   
   20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
   24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30   POSSIBILITY OF SUCH DAMAGE.
   31 
   32 *******************************************************************************/
   33 /* $FreeBSD$ */
   34 
   35 
   36 #include "e1000_api.h"
   37 #include "e1000_manage.h"
   38 
   39 static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
   40 
   41 /**
   42  *  e1000_calculate_checksum - Calculate checksum for buffer
   43  *  @buffer: pointer to EEPROM
   44  *  @length: size of EEPROM to calculate a checksum for
   45  *
   46  *  Calculates the checksum for some buffer on a specified length.  The
   47  *  checksum calculated is returned.
   48  **/
   49 static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
   50 {
   51         u32 i;
   52         u8  sum = 0;
   53 
   54         DEBUGFUNC("e1000_calculate_checksum");
   55 
   56         if (!buffer)
   57                 return 0;
   58 
   59         for (i = 0; i < length; i++)
   60                 sum += buffer[i];
   61 
   62         return (u8) (0 - sum);
   63 }
   64 
   65 /**
   66  *  e1000_mng_enable_host_if_generic - Checks host interface is enabled
   67  *  @hw: pointer to the HW structure
   68  *
   69  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
   70  *
   71  *  This function checks whether the HOST IF is enabled for command operaton
   72  *  and also checks whether the previous command is completed.  It busy waits
   73  *  in case of previous command is not completed.
   74  **/
   75 s32 e1000_mng_enable_host_if_generic(struct e1000_hw * hw)
   76 {
   77         u32 hicr;
   78         s32 ret_val = E1000_SUCCESS;
   79         u8  i;
   80 
   81         DEBUGFUNC("e1000_mng_enable_host_if_generic");
   82 
   83         /* Check that the host interface is enabled. */
   84         hicr = E1000_READ_REG(hw, E1000_HICR);
   85         if ((hicr & E1000_HICR_EN) == 0) {
   86                 DEBUGOUT("E1000_HOST_EN bit disabled.\n");
   87                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
   88                 goto out;
   89         }
   90         /* check the previous command is completed */
   91         for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
   92                 hicr = E1000_READ_REG(hw, E1000_HICR);
   93                 if (!(hicr & E1000_HICR_C))
   94                         break;
   95                 msec_delay_irq(1);
   96         }
   97 
   98         if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
   99                 DEBUGOUT("Previous command timeout failed .\n");
  100                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
  101                 goto out;
  102         }
  103 
  104 out:
  105         return ret_val;
  106 }
  107 
  108 /**
  109  *  e1000_check_mng_mode_generic - Generic check managament mode
  110  *  @hw: pointer to the HW structure
  111  *
  112  *  Reads the firmware semaphore register and returns true (>0) if
  113  *  manageability is enabled, else false (0).
  114  **/
  115 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
  116 {
  117         u32 fwsm;
  118 
  119         DEBUGFUNC("e1000_check_mng_mode_generic");
  120 
  121         fwsm = E1000_READ_REG(hw, E1000_FWSM);
  122 
  123         return ((fwsm & E1000_FWSM_MODE_MASK) ==
  124                 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
  125 }
  126 
  127 /**
  128  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on TX
  129  *  @hw: pointer to the HW structure
  130  *
  131  *  Enables packet filtering on transmit packets if manageability is enabled
  132  *  and host interface is enabled.
  133  **/
  134 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
  135 {
  136         struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
  137         u32 *buffer = (u32 *)&hw->mng_cookie;
  138         u32 offset;
  139         s32 ret_val, hdr_csum, csum;
  140         u8 i, len;
  141         bool tx_filter = TRUE;
  142 
  143         DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
  144 
  145         /* No manageability, no filtering */
  146         if (!e1000_check_mng_mode(hw)) {
  147                 tx_filter = FALSE;
  148                 goto out;
  149         }
  150 
  151         /*
  152          * If we can't read from the host interface for whatever
  153          * reason, disable filtering.
  154          */
  155         ret_val = e1000_mng_enable_host_if(hw);
  156         if (ret_val != E1000_SUCCESS) {
  157                 tx_filter = FALSE;
  158                 goto out;
  159         }
  160 
  161         /* Read in the header.  Length and offset are in dwords. */
  162         len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
  163         offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
  164         for (i = 0; i < len; i++) {
  165                 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
  166                                                            E1000_HOST_IF,
  167                                                            offset + i);
  168         }
  169         hdr_csum = hdr->checksum;
  170         hdr->checksum = 0;
  171         csum = e1000_calculate_checksum((u8 *)hdr,
  172                                         E1000_MNG_DHCP_COOKIE_LENGTH);
  173         /*
  174          * If either the checksums or signature don't match, then
  175          * the cookie area isn't considered valid, in which case we
  176          * take the safe route of assuming Tx filtering is enabled.
  177          */
  178         if (hdr_csum != csum)
  179                 goto out;
  180         if (hdr->signature != E1000_IAMT_SIGNATURE)
  181                 goto out;
  182 
  183         /* Cookie area is valid, make the final check for filtering. */
  184         if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING))
  185                 tx_filter = FALSE;
  186 
  187 out:
  188         hw->mac.tx_pkt_filtering = tx_filter;
  189         return tx_filter;
  190 }
  191 
  192 /**
  193  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
  194  *  @hw: pointer to the HW structure
  195  *  @buffer: pointer to the host interface
  196  *  @length: size of the buffer
  197  *
  198  *  Writes the DHCP information to the host interface.
  199  **/
  200 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw * hw, u8 *buffer,
  201                                       u16 length)
  202 {
  203         struct e1000_host_mng_command_header hdr;
  204         s32 ret_val;
  205         u32 hicr;
  206 
  207         DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
  208 
  209         hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
  210         hdr.command_length = length;
  211         hdr.reserved1 = 0;
  212         hdr.reserved2 = 0;
  213         hdr.checksum = 0;
  214 
  215         /* Enable the host interface */
  216         ret_val = e1000_mng_enable_host_if(hw);
  217         if (ret_val)
  218                 goto out;
  219 
  220         /* Populate the host interface with the contents of "buffer". */
  221         ret_val = e1000_mng_host_if_write(hw, buffer, length,
  222                                           sizeof(hdr), &(hdr.checksum));
  223         if (ret_val)
  224                 goto out;
  225 
  226         /* Write the manageability command header */
  227         ret_val = e1000_mng_write_cmd_header(hw, &hdr);
  228         if (ret_val)
  229                 goto out;
  230 
  231         /* Tell the ARC a new command is pending. */
  232         hicr = E1000_READ_REG(hw, E1000_HICR);
  233         E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
  234 
  235 out:
  236         return ret_val;
  237 }
  238 
  239 /**
  240  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
  241  *  @hw: pointer to the HW structure
  242  *  @hdr: pointer to the host interface command header
  243  *
  244  *  Writes the command header after does the checksum calculation.
  245  **/
  246 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw * hw,
  247                                        struct e1000_host_mng_command_header * hdr)
  248 {
  249         u16 i, length = sizeof(struct e1000_host_mng_command_header);
  250 
  251         DEBUGFUNC("e1000_mng_write_cmd_header_generic");
  252 
  253         /* Write the whole command header structure with new checksum. */
  254 
  255         hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
  256 
  257         length >>= 2;
  258         /* Write the relevant command block into the ram area. */
  259         for (i = 0; i < length; i++) {
  260                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
  261                                             *((u32 *) hdr + i));
  262                 E1000_WRITE_FLUSH(hw);
  263         }
  264 
  265         return E1000_SUCCESS;
  266 }
  267 
  268 /**
  269  *  e1000_mng_host_if_write_generic - Writes to the manageability host interface
  270  *  @hw: pointer to the HW structure
  271  *  @buffer: pointer to the host interface buffer
  272  *  @length: size of the buffer
  273  *  @offset: location in the buffer to write to
  274  *  @sum: sum of the data (not checksum)
  275  *
  276  *  This function writes the buffer content at the offset given on the host if.
  277  *  It also does alignment considerations to do the writes in most efficient
  278  *  way.  Also fills up the sum of the buffer in *buffer parameter.
  279  **/
  280 s32 e1000_mng_host_if_write_generic(struct e1000_hw * hw, u8 *buffer,
  281                                     u16 length, u16 offset, u8 *sum)
  282 {
  283         u8 *tmp;
  284         u8 *bufptr = buffer;
  285         u32 data = 0;
  286         s32 ret_val = E1000_SUCCESS;
  287         u16 remaining, i, j, prev_bytes;
  288 
  289         DEBUGFUNC("e1000_mng_host_if_write_generic");
  290 
  291         /* sum = only sum of the data and it is not checksum */
  292 
  293         if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
  294                 ret_val = -E1000_ERR_PARAM;
  295                 goto out;
  296         }
  297 
  298         tmp = (u8 *)&data;
  299         prev_bytes = offset & 0x3;
  300         offset >>= 2;
  301 
  302         if (prev_bytes) {
  303                 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
  304                 for (j = prev_bytes; j < sizeof(u32); j++) {
  305                         *(tmp + j) = *bufptr++;
  306                         *sum += *(tmp + j);
  307                 }
  308                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
  309                 length -= j - prev_bytes;
  310                 offset++;
  311         }
  312 
  313         remaining = length & 0x3;
  314         length -= remaining;
  315 
  316         /* Calculate length in DWORDs */
  317         length >>= 2;
  318 
  319         /*
  320          * The device driver writes the relevant command block into the
  321          * ram area.
  322          */
  323         for (i = 0; i < length; i++) {
  324                 for (j = 0; j < sizeof(u32); j++) {
  325                         *(tmp + j) = *bufptr++;
  326                         *sum += *(tmp + j);
  327                 }
  328 
  329                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
  330         }
  331         if (remaining) {
  332                 for (j = 0; j < sizeof(u32); j++) {
  333                         if (j < remaining)
  334                                 *(tmp + j) = *bufptr++;
  335                         else
  336                                 *(tmp + j) = 0;
  337 
  338                         *sum += *(tmp + j);
  339                 }
  340                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
  341         }
  342 
  343 out:
  344         return ret_val;
  345 }
  346 
  347 /**
  348  *  e1000_enable_mng_pass_thru - Enable processing of ARP's
  349  *  @hw: pointer to the HW structure
  350  *
  351  *  Verifies the hardware needs to allow ARPs to be processed by the host.
  352  **/
  353 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
  354 {
  355         u32 manc;
  356         u32 fwsm, factps;
  357         bool ret_val = FALSE;
  358 
  359         DEBUGFUNC("e1000_enable_mng_pass_thru");
  360 
  361         if (!hw->mac.asf_firmware_present)
  362                 goto out;
  363 
  364         manc = E1000_READ_REG(hw, E1000_MANC);
  365 
  366         if (!(manc & E1000_MANC_RCV_TCO_EN) ||
  367             !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
  368                 goto out;
  369 
  370         if (hw->mac.arc_subsystem_valid) {
  371                 fwsm = E1000_READ_REG(hw, E1000_FWSM);
  372                 factps = E1000_READ_REG(hw, E1000_FACTPS);
  373 
  374                 if (!(factps & E1000_FACTPS_MNGCG) &&
  375                     ((fwsm & E1000_FWSM_MODE_MASK) ==
  376                      (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
  377                         ret_val = TRUE;
  378                         goto out;
  379                 }
  380         } else {
  381                 if ((manc & E1000_MANC_SMBUS_EN) &&
  382                     !(manc & E1000_MANC_ASF_EN)) {
  383                         ret_val = TRUE;
  384                         goto out;
  385                 }
  386         }
  387 
  388 out:
  389         return ret_val;
  390 }
  391 

Cache object: 4def44613f558e0fde286899b197ae37


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.