Any updates on this?

> Am 09.03.2015 um 07:32 schrieb Patrick Wildt <m...@patrick-wildt.de>:
> 
> Hi,
> 
> this diff adds support for a special configuration of i210/i211 chips.
> 
> Those can have a OTP chip instead of the usual EEPROM, so this diff
> adds the infrastructure to read needed data from OTP and have it not
> bail out when there's no EEPROM.
> 
> \Patrick
> 
> diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
> index 8717fa4..10cdc52 100644
> --- sys/dev/pci/if_em.c
> +++ sys/dev/pci/if_em.c
> @@ -1775,7 +1775,8 @@ em_hardware_init(struct em_softc *sc)
>       sc->tx_fifo_head = 0;
> 
>       /* Make sure we have a good EEPROM before we read from it */
> -     if (em_validate_eeprom_checksum(&sc->hw) < 0) {
> +     if (em_get_flash_presence_i210(&sc->hw) &&
> +         em_validate_eeprom_checksum(&sc->hw) < 0) {
>               /*
>                * Some PCIe parts fail the first check due to
>                * the link being in sleep state, call it again,
> @@ -1788,7 +1789,8 @@ em_hardware_init(struct em_softc *sc)
>               }
>       }
> 
> -     if (em_read_part_num(&sc->hw, &(sc->part_num)) < 0) {
> +     if (em_get_flash_presence_i210(&sc->hw) &&
> +         em_read_part_num(&sc->hw, &(sc->part_num)) < 0) {
>               printf("%s: EEPROM read error while reading part number\n",
>                      sc->sc_dv.dv_xname);
>               return (EIO);
> diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c
> index 16cd3ee..4994c4d 100644
> --- sys/dev/pci/if_em_hw.c
> +++ sys/dev/pci/if_em_hw.c
> @@ -113,6 +113,9 @@ static int32_t    em_read_eeprom_ich8(struct em_hw *, 
> uint16_t, uint16_t,
>                   uint16_t *);
> static int32_t        em_write_eeprom_ich8(struct em_hw *, uint16_t, uint16_t,
>                   uint16_t *);
> +static int32_t       em_read_invm_i210(struct em_hw *, uint16_t, uint16_t,
> +                 uint16_t *);
> +static int32_t       em_read_invm_word_i210(struct em_hw *, uint16_t, 
> uint16_t *);
> static void   em_release_software_flag(struct em_hw *);
> static int32_t        em_set_d3_lplu_state(struct em_hw *, boolean_t);
> static int32_t        em_set_d0_lplu_state(struct em_hw *, boolean_t);
> @@ -5523,6 +5526,12 @@ em_init_eeprom_params(struct em_hw *hw)
>                       eecd &= ~E1000_EECD_AUPDEN;
>                       E1000_WRITE_REG(hw, EECD, eecd);
>               }
> +             if (em_get_flash_presence_i210(hw) == FALSE) {
> +                     eeprom->type = em_eeprom_invm;
> +                     eeprom->word_size = INVM_SIZE;
> +                     eeprom->use_eerd = FALSE;
> +                     eeprom->use_eewr = FALSE;
> +             }
>               break;
>       case em_80003es2lan:
>               eeprom->type = em_eeprom_spi;
> @@ -5986,6 +5995,7 @@ em_read_eeprom(struct em_hw *hw, uint16_t offset, 
> uint16_t words,
>        * FW or other port software does not interrupt.
>        */
>       if (em_is_onboard_nvm_eeprom(hw) == TRUE &&
> +         em_get_flash_presence_i210(hw) == TRUE &&
>           hw->eeprom.use_eerd == FALSE) {
>               /* Prepare the EEPROM for bit-bang reading */
>               if (em_acquire_eeprom(hw) != E1000_SUCCESS)
> @@ -5998,6 +6008,11 @@ em_read_eeprom(struct em_hw *hw, uint16_t offset, 
> uint16_t words,
>       /* ICH EEPROM access is done via the ICH flash controller */
>       if (eeprom->type == em_eeprom_ich8)
>               return em_read_eeprom_ich8(hw, offset, words, data);
> +
> +     /* Some i210/i211 have a special OTP chip */
> +     if (eeprom->type == em_eeprom_invm)
> +             return em_read_invm_i210(hw, offset, words, data);
> +
>       /*
>        * Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
>        * acquired the EEPROM at this point, so any returns should relase it
> @@ -6182,6 +6197,28 @@ em_is_onboard_nvm_eeprom(struct em_hw *hw)
> }
> 
> /******************************************************************************
> + * Check if flash device is detected.
> + *
> + * hw - Struct containing variables accessed by shared code
> + 
> *****************************************************************************/
> +boolean_t
> +em_get_flash_presence_i210(struct em_hw *hw)
> +{
> +     uint32_t eecd;
> +     DEBUGFUNC("em_get_flash_presence_i210");
> +
> +     if (hw->mac_type != em_i210)
> +             return TRUE;
> +
> +     eecd = E1000_READ_REG(hw, EECD);
> +
> +     if (eecd & E1000_EECD_FLUPD)
> +             return TRUE;
> +
> +     return FALSE;
> +}
> +
> +/******************************************************************************
>  * Verifies that the EEPROM has a valid checksum
>  *
>  * hw - Struct containing variables accessed by shared code
> @@ -9730,6 +9767,84 @@ em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t 
> bank)
>       return error;
> }
> 
> +/******************************************************************************
> + * Reads 16-bit words from the OTP. Return error when the word is not
> + * stored in OTP.
> + *
> + * hw - Struct containing variables accessed by shared code
> + * offset - offset of word in the OTP to read
> + * data - word read from the OTP
> + * words - number of words to read
> + 
> *****************************************************************************/
> +STATIC int32_t
> +em_read_invm_i210(struct em_hw *hw, uint16_t offset, uint16_t words,
> +    uint16_t *data)
> +{
> +     int32_t  ret_val = E1000_SUCCESS;
> +
> +     switch (offset)
> +     {
> +     case EEPROM_MAC_ADDRESS:
> +     case EEPROM_MAC_ADDRESS_WORD1:
> +     case EEPROM_MAC_ADDRESS_WORD2:
> +             /* Generate random MAC address if there's none. */
> +             ret_val = em_read_invm_word_i210(hw, offset, data);
> +             if (ret_val != E1000_SUCCESS) {
> +                     *data = 0xFFFF;
> +                     ret_val = E1000_SUCCESS;
> +             }
> +             break;
> +     case EEPROM_ID_LED_SETTINGS:
> +             ret_val = em_read_invm_word_i210(hw, offset, data);
> +             if (ret_val != E1000_SUCCESS) {
> +                     *data = ID_LED_RESERVED_FFFF;
> +                     ret_val = E1000_SUCCESS;
> +             }
> +             break;
> +     }
> +
> +     return ret_val;
> +}
> +
> +/******************************************************************************
> + * Reads 16-bit words from the OTP. Return error when the word is not
> + * stored in OTP.
> + *
> + * hw - Struct containing variables accessed by shared code
> + * offset - offset of word in the OTP to read
> + * data - word read from the OTP
> + 
> *****************************************************************************/
> +STATIC int32_t
> +em_read_invm_word_i210(struct em_hw *hw, uint16_t address, uint16_t *data)
> +{
> +     int32_t  error = -E1000_NOT_IMPLEMENTED;
> +     uint32_t invm_dword;
> +     uint16_t i;
> +     uint8_t record_type, word_address;
> +
> +     for (i = 0; i < INVM_SIZE; i++) {
> +             invm_dword = E1000_READ_REG(hw, INVM_DATA_REG(i));
> +             /* Get record type */
> +             record_type = INVM_DWORD_TO_RECORD_TYPE(invm_dword);
> +             if (record_type == INVM_UNINITIALIZED_STRUCTURE)
> +                     break;
> +             if (record_type == INVM_CSR_AUTOLOAD_STRUCTURE)
> +                     i += INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS;
> +             if (record_type == INVM_RSA_KEY_SHA256_STRUCTURE)
> +                     i += INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS;
> +             if (record_type == INVM_WORD_AUTOLOAD_STRUCTURE) {
> +                     word_address = INVM_DWORD_TO_WORD_ADDRESS(invm_dword);
> +                     if (word_address == address) {
> +                             *data = INVM_DWORD_TO_WORD_DATA(invm_dword);
> +                             error = E1000_SUCCESS;
> +                             break;
> +                     }
> +             }
> +     }
> +
> +     return error;
> +}
> +
> STATIC int32_t
> em_init_lcd_from_nvm_config_region(struct em_hw *hw, uint32_t cnf_base_addr,
>     uint32_t cnf_size)
> diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h
> index 3dd5488..a9bd1ca 100644
> --- sys/dev/pci/if_em_hw.h
> +++ sys/dev/pci/if_em_hw.h
> @@ -93,6 +93,7 @@ typedef enum {
>     em_eeprom_microwire,
>     em_eeprom_flash,
>     em_eeprom_ich8,
> +    em_eeprom_invm,
>     em_eeprom_none, /* No NVM support */
>     em_num_eeprom_types
> } em_eeprom_type;
> @@ -409,6 +410,7 @@ int32_t em_validate_eeprom_checksum(struct em_hw *hw);
> int32_t em_update_eeprom_checksum(struct em_hw *hw);
> int32_t em_write_eeprom(struct em_hw *hw, uint16_t reg, uint16_t words, 
> uint16_t *data);
> int32_t em_read_mac_addr(struct em_hw * hw);
> +boolean_t em_get_flash_presence_i210(struct em_hw *);
> 
> /* Filters (multicast, vlan, receive) */
> void em_mc_addr_list_update(struct em_hw *hw, uint8_t * mc_addr_list, 
> uint32_t mc_addr_count,
> @@ -2464,6 +2466,9 @@ struct em_host_command_info {
> #define EEPROM_SIZE_MASK        0x1C00
> 
> /* EEPROM Word Offsets */
> +#define EEPROM_MAC_ADDRESS            0x0000
> +#define EEPROM_MAC_ADDRESS_WORD1      0x0001
> +#define EEPROM_MAC_ADDRESS_WORD2      0x0002
> #define EEPROM_COMPAT                 0x0003
> #define EEPROM_ID_LED_SETTINGS        0x0004
> #define EEPROM_VERSION                0x0005
> @@ -3744,6 +3749,25 @@ union ich8_hws_flash_regacc {
> #define I82579_MSE_THRESHOLD  0x084F  /* Mean Square Error Threshold */
> #define I82579_MSE_LINK_DOWN  0x2411  /* MSE count before dropping link */
> 
> +/* INVM Registers for i210 */
> +#define E1000_INVM_DATA_REG(reg)             (0x12120 + 4*(reg))
> +#define E1000_82542_INVM_DATA_REG(reg)               E1000_INVM_DATA_REG(reg)
> +#define INVM_SIZE                            64 /* Number of INVM Data 
> Registers */
> +
> +#define INVM_DWORD_TO_RECORD_TYPE(dword)     ((dword) & 0x7)
> +#define INVM_DWORD_TO_WORD_ADDRESS(dword)    (((dword) & 0x0000FE00) >> 9)
> +#define INVM_DWORD_TO_WORD_DATA(dword)               (((dword) & 0xFFFF0000) 
> >> 16)
> +
> +#define INVM_UNINITIALIZED_STRUCTURE         0x0
> +#define INVM_WORD_AUTOLOAD_STRUCTURE         0x1
> +#define INVM_CSR_AUTOLOAD_STRUCTURE          0x2
> +#define INVM_PHY_REGISTER_AUTOLOAD_STRUCTURE 0x3
> +#define INVM_RSA_KEY_SHA256_STRUCTURE                0x4
> +#define INVM_INVALIDATED_STRUCTURE           0x5
> +
> +#define INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS      8
> +#define INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS        1
> +
> #define PHY_UPPER_SHIFT                   21
> #define BM_PHY_REG(page, reg) \
>         (((reg) & MAX_PHY_REG_ADDRESS) |\
> 


Reply via email to