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/e1000/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-2010, 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: releng/9.0/sys/dev/e1000/e1000_manage.c 218530 2011-02-11 01:00:26Z jfv $*/
   34 
   35 #include "e1000_api.h"
   36 
   37 /**
   38  *  e1000_calculate_checksum - Calculate checksum for buffer
   39  *  @buffer: pointer to EEPROM
   40  *  @length: size of EEPROM to calculate a checksum for
   41  *
   42  *  Calculates the checksum for some buffer on a specified length.  The
   43  *  checksum calculated is returned.
   44  **/
   45 u8 e1000_calculate_checksum(u8 *buffer, u32 length)
   46 {
   47         u32 i;
   48         u8 sum = 0;
   49 
   50         DEBUGFUNC("e1000_calculate_checksum");
   51 
   52         if (!buffer)
   53                 return 0;
   54 
   55         for (i = 0; i < length; i++)
   56                 sum += buffer[i];
   57 
   58         return (u8) (0 - sum);
   59 }
   60 
   61 /**
   62  *  e1000_mng_enable_host_if_generic - Checks host interface is enabled
   63  *  @hw: pointer to the HW structure
   64  *
   65  *  Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND
   66  *
   67  *  This function checks whether the HOST IF is enabled for command operation
   68  *  and also checks whether the previous command is completed.  It busy waits
   69  *  in case of previous command is not completed.
   70  **/
   71 s32 e1000_mng_enable_host_if_generic(struct e1000_hw *hw)
   72 {
   73         u32 hicr;
   74         s32 ret_val = E1000_SUCCESS;
   75         u8 i;
   76 
   77         DEBUGFUNC("e1000_mng_enable_host_if_generic");
   78 
   79         if (!(hw->mac.arc_subsystem_valid)) {
   80                 DEBUGOUT("ARC subsystem not valid.\n");
   81                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
   82                 goto out;
   83         }
   84 
   85         /* Check that the host interface is enabled. */
   86         hicr = E1000_READ_REG(hw, E1000_HICR);
   87         if ((hicr & E1000_HICR_EN) == 0) {
   88                 DEBUGOUT("E1000_HOST_EN bit disabled.\n");
   89                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
   90                 goto out;
   91         }
   92         /* check the previous command is completed */
   93         for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
   94                 hicr = E1000_READ_REG(hw, E1000_HICR);
   95                 if (!(hicr & E1000_HICR_C))
   96                         break;
   97                 msec_delay_irq(1);
   98         }
   99 
  100         if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
  101                 DEBUGOUT("Previous command timeout failed .\n");
  102                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
  103                 goto out;
  104         }
  105 
  106 out:
  107         return ret_val;
  108 }
  109 
  110 /**
  111  *  e1000_check_mng_mode_generic - Generic check management mode
  112  *  @hw: pointer to the HW structure
  113  *
  114  *  Reads the firmware semaphore register and returns TRUE (>0) if
  115  *  manageability is enabled, else FALSE (0).
  116  **/
  117 bool e1000_check_mng_mode_generic(struct e1000_hw *hw)
  118 {
  119         u32 fwsm = E1000_READ_REG(hw, E1000_FWSM);
  120 
  121         DEBUGFUNC("e1000_check_mng_mode_generic");
  122 
  123 
  124         return (fwsm & E1000_FWSM_MODE_MASK) ==
  125                 (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT);
  126 }
  127 
  128 /**
  129  *  e1000_enable_tx_pkt_filtering_generic - Enable packet filtering on Tx
  130  *  @hw: pointer to the HW structure
  131  *
  132  *  Enables packet filtering on transmit packets if manageability is enabled
  133  *  and host interface is enabled.
  134  **/
  135 bool e1000_enable_tx_pkt_filtering_generic(struct e1000_hw *hw)
  136 {
  137         struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie;
  138         u32 *buffer = (u32 *)&hw->mng_cookie;
  139         u32 offset;
  140         s32 ret_val, hdr_csum, csum;
  141         u8 i, len;
  142 
  143         DEBUGFUNC("e1000_enable_tx_pkt_filtering_generic");
  144 
  145         hw->mac.tx_pkt_filtering = TRUE;
  146 
  147         /* No manageability, no filtering */
  148         if (!hw->mac.ops.check_mng_mode(hw)) {
  149                 hw->mac.tx_pkt_filtering = FALSE;
  150                 goto out;
  151         }
  152 
  153         /*
  154          * If we can't read from the host interface for whatever
  155          * reason, disable filtering.
  156          */
  157         ret_val = hw->mac.ops.mng_enable_host_if(hw);
  158         if (ret_val != E1000_SUCCESS) {
  159                 hw->mac.tx_pkt_filtering = FALSE;
  160                 goto out;
  161         }
  162 
  163         /* Read in the header.  Length and offset are in dwords. */
  164         len    = E1000_MNG_DHCP_COOKIE_LENGTH >> 2;
  165         offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2;
  166         for (i = 0; i < len; i++)
  167                 *(buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF,
  168                                                            offset + i);
  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) || (hdr->signature != E1000_IAMT_SIGNATURE)) {
  179                 hw->mac.tx_pkt_filtering = TRUE;
  180                 goto out;
  181         }
  182 
  183         /* Cookie area is valid, make the final check for filtering. */
  184         if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) {
  185                 hw->mac.tx_pkt_filtering = FALSE;
  186                 goto out;
  187         }
  188 
  189 out:
  190         return hw->mac.tx_pkt_filtering;
  191 }
  192 
  193 /**
  194  *  e1000_mng_write_dhcp_info_generic - Writes DHCP info to host interface
  195  *  @hw: pointer to the HW structure
  196  *  @buffer: pointer to the host interface
  197  *  @length: size of the buffer
  198  *
  199  *  Writes the DHCP information to the host interface.
  200  **/
  201 s32 e1000_mng_write_dhcp_info_generic(struct e1000_hw *hw, u8 *buffer,
  202                                       u16 length)
  203 {
  204         struct e1000_host_mng_command_header hdr;
  205         s32 ret_val;
  206         u32 hicr;
  207 
  208         DEBUGFUNC("e1000_mng_write_dhcp_info_generic");
  209 
  210         hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
  211         hdr.command_length = length;
  212         hdr.reserved1 = 0;
  213         hdr.reserved2 = 0;
  214         hdr.checksum = 0;
  215 
  216         /* Enable the host interface */
  217         ret_val = hw->mac.ops.mng_enable_host_if(hw);
  218         if (ret_val)
  219                 goto out;
  220 
  221         /* Populate the host interface with the contents of "buffer". */
  222         ret_val = hw->mac.ops.mng_host_if_write(hw, buffer, length,
  223                                           sizeof(hdr), &(hdr.checksum));
  224         if (ret_val)
  225                 goto out;
  226 
  227         /* Write the manageability command header */
  228         ret_val = hw->mac.ops.mng_write_cmd_header(hw, &hdr);
  229         if (ret_val)
  230                 goto out;
  231 
  232         /* Tell the ARC a new command is pending. */
  233         hicr = E1000_READ_REG(hw, E1000_HICR);
  234         E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
  235 
  236 out:
  237         return ret_val;
  238 }
  239 
  240 /**
  241  *  e1000_mng_write_cmd_header_generic - Writes manageability command header
  242  *  @hw: pointer to the HW structure
  243  *  @hdr: pointer to the host interface command header
  244  *
  245  *  Writes the command header after does the checksum calculation.
  246  **/
  247 s32 e1000_mng_write_cmd_header_generic(struct e1000_hw *hw,
  248                                     struct e1000_host_mng_command_header *hdr)
  249 {
  250         u16 i, length = sizeof(struct e1000_host_mng_command_header);
  251 
  252         DEBUGFUNC("e1000_mng_write_cmd_header_generic");
  253 
  254         /* Write the whole command header structure with new checksum. */
  255 
  256         hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length);
  257 
  258         length >>= 2;
  259         /* Write the relevant command block into the ram area. */
  260         for (i = 0; i < length; i++) {
  261                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, i,
  262                                             *((u32 *) hdr + i));
  263                 E1000_WRITE_FLUSH(hw);
  264         }
  265 
  266         return E1000_SUCCESS;
  267 }
  268 
  269 /**
  270  *  e1000_mng_host_if_write_generic - Write to the manageability host interface
  271  *  @hw: pointer to the HW structure
  272  *  @buffer: pointer to the host interface buffer
  273  *  @length: size of the buffer
  274  *  @offset: location in the buffer to write to
  275  *  @sum: sum of the data (not checksum)
  276  *
  277  *  This function writes the buffer content at the offset given on the host if.
  278  *  It also does alignment considerations to do the writes in most efficient
  279  *  way.  Also fills up the sum of the buffer in *buffer parameter.
  280  **/
  281 s32 e1000_mng_host_if_write_generic(struct e1000_hw *hw, u8 *buffer,
  282                                     u16 length, u16 offset, u8 *sum)
  283 {
  284         u8 *tmp;
  285         u8 *bufptr = buffer;
  286         u32 data = 0;
  287         s32 ret_val = E1000_SUCCESS;
  288         u16 remaining, i, j, prev_bytes;
  289 
  290         DEBUGFUNC("e1000_mng_host_if_write_generic");
  291 
  292         /* sum = only sum of the data and it is not checksum */
  293 
  294         if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
  295                 ret_val = -E1000_ERR_PARAM;
  296                 goto out;
  297         }
  298 
  299         tmp = (u8 *)&data;
  300         prev_bytes = offset & 0x3;
  301         offset >>= 2;
  302 
  303         if (prev_bytes) {
  304                 data = E1000_READ_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset);
  305                 for (j = prev_bytes; j < sizeof(u32); j++) {
  306                         *(tmp + j) = *bufptr++;
  307                         *sum += *(tmp + j);
  308                 }
  309                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset, data);
  310                 length -= j - prev_bytes;
  311                 offset++;
  312         }
  313 
  314         remaining = length & 0x3;
  315         length -= remaining;
  316 
  317         /* Calculate length in DWORDs */
  318         length >>= 2;
  319 
  320         /*
  321          * The device driver writes the relevant command block into the
  322          * ram area.
  323          */
  324         for (i = 0; i < length; i++) {
  325                 for (j = 0; j < sizeof(u32); j++) {
  326                         *(tmp + j) = *bufptr++;
  327                         *sum += *(tmp + j);
  328                 }
  329 
  330                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i,
  331                                             data);
  332         }
  333         if (remaining) {
  334                 for (j = 0; j < sizeof(u32); j++) {
  335                         if (j < remaining)
  336                                 *(tmp + j) = *bufptr++;
  337                         else
  338                                 *(tmp + j) = 0;
  339 
  340                         *sum += *(tmp + j);
  341                 }
  342                 E1000_WRITE_REG_ARRAY_DWORD(hw, E1000_HOST_IF, offset + i, data);
  343         }
  344 
  345 out:
  346         return ret_val;
  347 }
  348 
  349 /**
  350  *  e1000_enable_mng_pass_thru - Check if management passthrough is needed
  351  *  @hw: pointer to the HW structure
  352  *
  353  *  Verifies the hardware needs to leave interface enabled so that frames can
  354  *  be directed to and from the management interface.
  355  **/
  356 bool e1000_enable_mng_pass_thru(struct e1000_hw *hw)
  357 {
  358         u32 manc;
  359         u32 fwsm, factps;
  360         bool ret_val = FALSE;
  361 
  362         DEBUGFUNC("e1000_enable_mng_pass_thru");
  363 
  364         if (!hw->mac.asf_firmware_present)
  365                 goto out;
  366 
  367         manc = E1000_READ_REG(hw, E1000_MANC);
  368 
  369         if (!(manc & E1000_MANC_RCV_TCO_EN))
  370                 goto out;
  371 
  372         if (hw->mac.has_fwsm) {
  373                 fwsm = E1000_READ_REG(hw, E1000_FWSM);
  374                 factps = E1000_READ_REG(hw, E1000_FACTPS);
  375 
  376                 if (!(factps & E1000_FACTPS_MNGCG) &&
  377                     ((fwsm & E1000_FWSM_MODE_MASK) ==
  378                      (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) {
  379                         ret_val = TRUE;
  380                         goto out;
  381                 }
  382         } else if ((hw->mac.type == e1000_82574) ||
  383                    (hw->mac.type == e1000_82583)) {
  384                 u16 data;
  385 
  386                 factps = E1000_READ_REG(hw, E1000_FACTPS);
  387                 e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
  388 
  389                 if (!(factps & E1000_FACTPS_MNGCG) &&
  390                     ((data & E1000_NVM_INIT_CTRL2_MNGM) ==
  391                      (e1000_mng_mode_pt << 13))) {
  392                         ret_val = TRUE;
  393                         goto out;
  394                 }
  395         } else if ((manc & E1000_MANC_SMBUS_EN) &&
  396                     !(manc & E1000_MANC_ASF_EN)) {
  397                         ret_val = TRUE;
  398                         goto out;
  399         }
  400 
  401 out:
  402         return ret_val;
  403 }
  404 
  405 /**
  406  *  e1000_host_interface_command - Writes buffer to host interface
  407  *  @hw: pointer to the HW structure
  408  *  @buffer: contains a command to write
  409  *  @length: the byte length of the buffer, must be multiple of 4 bytes
  410  *
  411  *  Writes a buffer to the Host Interface.  Upon success, returns E1000_SUCCESS
  412  *  else returns E1000_ERR_HOST_INTERFACE_COMMAND.
  413  **/
  414 s32 e1000_host_interface_command(struct e1000_hw *hw, u8 *buffer, u32 length)
  415 {
  416         u32 hicr, i;
  417         s32 ret_val = E1000_SUCCESS;
  418 
  419         DEBUGFUNC("e1000_host_interface_command");
  420 
  421         if (!(hw->mac.arc_subsystem_valid)) {
  422                 DEBUGOUT("Hardware doesn't support host interface command.\n");
  423                 goto out;
  424         }
  425 
  426         if (!hw->mac.asf_firmware_present) {
  427                 DEBUGOUT("Firmware is not present.\n");
  428                 goto out;
  429         }
  430 
  431         if (length == 0 || length & 0x3 ||
  432             length > E1000_HI_MAX_BLOCK_BYTE_LENGTH) {
  433                 DEBUGOUT("Buffer length failure.\n");
  434                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
  435                 goto out;
  436         }
  437 
  438         /* Check that the host interface is enabled. */
  439         hicr = E1000_READ_REG(hw, E1000_HICR);
  440         if ((hicr & E1000_HICR_EN) == 0) {
  441                 DEBUGOUT("E1000_HOST_EN bit disabled.\n");
  442                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
  443                 goto out;
  444         }
  445 
  446         /* Calculate length in DWORDs */
  447         length >>= 2;
  448 
  449         /*
  450          * The device driver writes the relevant command block
  451          * into the ram area.
  452          */
  453         for (i = 0; i < length; i++)
  454                 E1000_WRITE_REG_ARRAY_DWORD(hw,
  455                                             E1000_HOST_IF,
  456                                             i,
  457                                             *((u32 *)buffer + i));
  458 
  459         /* Setting this bit tells the ARC that a new command is pending. */
  460         E1000_WRITE_REG(hw, E1000_HICR, hicr | E1000_HICR_C);
  461 
  462         for (i = 0; i < E1000_HI_COMMAND_TIMEOUT; i++) {
  463                 hicr = E1000_READ_REG(hw, E1000_HICR);
  464                 if (!(hicr & E1000_HICR_C))
  465                         break;
  466                 msec_delay(1);
  467         }
  468 
  469         /* Check command successful completion. */
  470         if (i == E1000_HI_COMMAND_TIMEOUT ||
  471             (!(E1000_READ_REG(hw, E1000_HICR) & E1000_HICR_SV))) {
  472                 DEBUGOUT("Command has failed with no status valid.\n");
  473                 ret_val = -E1000_ERR_HOST_INTERFACE_COMMAND;
  474                 goto out;
  475         }
  476 
  477         for (i = 0; i < length; i++)
  478                 *((u32 *)buffer + i) = E1000_READ_REG_ARRAY_DWORD(hw,
  479                                                                   E1000_HOST_IF,
  480                                                                   i);
  481 
  482 out:
  483         return ret_val;
  484 }
  485 

Cache object: 043f1019a8fb935b8a2290ed1cae7816


[ 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.