📄 ixgb_hw.c
字号:
* address registers and the multicast table. Uses receive address registers * for the first 15 multicast addresses, and hashes the rest into the * multicast table. *****************************************************************************/voidixgb_mc_addr_list_update(struct ixgb_hw *hw, uint8_t *mc_addr_list, uint32_t mc_addr_count, uint32_t pad){ uint32_t hash_value; uint32_t i; uint32_t rar_used_count = 1; /* RAR[0] is used for our MAC address */ DEBUGFUNC("ixgb_mc_addr_list_update"); /* Set the new number of MC addresses that we are being requested to use. */ hw->num_mc_addrs = mc_addr_count; /* Clear RAR[1-15] */ DEBUGOUT(" Clearing RAR[1-15]\n"); for(i = rar_used_count; i < IXGB_RAR_ENTRIES; i++) { IXGB_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); IXGB_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); } /* Clear the MTA */ DEBUGOUT(" Clearing MTA\n"); for(i = 0; i < IXGB_MC_TBL_SIZE; i++) { IXGB_WRITE_REG_ARRAY(hw, MTA, i, 0); } /* Add the new addresses */ for(i = 0; i < mc_addr_count; i++) { DEBUGOUT(" Adding the multicast addresses:\n"); DEBUGOUT7(" MC Addr #%d =%.2X %.2X %.2X %.2X %.2X %.2X\n", i, mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)], mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 1], mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 2], mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 3], mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 4], mc_addr_list[i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad) + 5]); /* Place this multicast address in the RAR if there is room, * * else put it in the MTA */ if(rar_used_count < IXGB_RAR_ENTRIES) { ixgb_rar_set(hw, mc_addr_list + (i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad)), rar_used_count); DEBUGOUT1("Added a multicast address to RAR[%d]\n", i); rar_used_count++; } else { hash_value = ixgb_hash_mc_addr(hw, mc_addr_list + (i * (IXGB_ETH_LENGTH_OF_ADDRESS + pad))); DEBUGOUT1(" Hash value = 0x%03X\n", hash_value); ixgb_mta_set(hw, hash_value); } } DEBUGOUT("MC Update Complete\n"); return;}/****************************************************************************** * Hashes an address to determine its location in the multicast table * * hw - Struct containing variables accessed by shared code * mc_addr - the multicast address to hash * * Returns: * The hash value *****************************************************************************/static uint32_tixgb_hash_mc_addr(struct ixgb_hw *hw, uint8_t *mc_addr){ uint32_t hash_value = 0; DEBUGFUNC("ixgb_hash_mc_addr"); /* The portion of the address that is used for the hash table is * determined by the mc_filter_type setting. */ switch (hw->mc_filter_type) { /* [0] [1] [2] [3] [4] [5] * 01 AA 00 12 34 56 * LSB MSB - According to H/W docs */ case 0: /* [47:36] i.e. 0x563 for above example address */ hash_value = ((mc_addr[4] >> 4) | (((uint16_t) mc_addr[5]) << 4)); break; case 1: /* [46:35] i.e. 0xAC6 for above example address */ hash_value = ((mc_addr[4] >> 3) | (((uint16_t) mc_addr[5]) << 5)); break; case 2: /* [45:34] i.e. 0x5D8 for above example address */ hash_value = ((mc_addr[4] >> 2) | (((uint16_t) mc_addr[5]) << 6)); break; case 3: /* [43:32] i.e. 0x634 for above example address */ hash_value = ((mc_addr[4]) | (((uint16_t) mc_addr[5]) << 8)); break; default: /* Invalid mc_filter_type, what should we do? */ DEBUGOUT("MC filter type param set incorrectly\n"); ASSERT(0); break; } hash_value &= 0xFFF; return (hash_value);}/****************************************************************************** * Sets the bit in the multicast table corresponding to the hash value. * * hw - Struct containing variables accessed by shared code * hash_value - Multicast address hash value *****************************************************************************/static voidixgb_mta_set(struct ixgb_hw *hw, uint32_t hash_value){ uint32_t hash_bit, hash_reg; uint32_t mta_reg; /* The MTA is a register array of 128 32-bit registers. * It is treated like an array of 4096 bits. We want to set * bit BitArray[hash_value]. So we figure out what register * the bit is in, read it, OR in the new bit, then write * back the new value. The register is determined by the * upper 7 bits of the hash value and the bit within that * register are determined by the lower 5 bits of the value. */ hash_reg = (hash_value >> 5) & 0x7F; hash_bit = hash_value & 0x1F; mta_reg = IXGB_READ_REG_ARRAY(hw, MTA, hash_reg); mta_reg |= (1 << hash_bit); IXGB_WRITE_REG_ARRAY(hw, MTA, hash_reg, mta_reg); return;}/****************************************************************************** * Puts an ethernet address into a receive address register. * * hw - Struct containing variables accessed by shared code * addr - Address to put into receive address register * index - Receive address register to write *****************************************************************************/voidixgb_rar_set(struct ixgb_hw *hw, uint8_t *addr, uint32_t index){ uint32_t rar_low, rar_high; DEBUGFUNC("ixgb_rar_set"); /* HW expects these in little endian so we reverse the byte order * from network order (big endian) to little endian */ rar_low = ((uint32_t) addr[0] | ((uint32_t)addr[1] << 8) | ((uint32_t)addr[2] << 16) | ((uint32_t)addr[3] << 24)); rar_high = ((uint32_t) addr[4] | ((uint32_t)addr[5] << 8) | IXGB_RAH_AV); IXGB_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); IXGB_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); return;}/****************************************************************************** * Writes a value to the specified offset in the VLAN filter table. * * hw - Struct containing variables accessed by shared code * offset - Offset in VLAN filer table to write * value - Value to write into VLAN filter table *****************************************************************************/voidixgb_write_vfta(struct ixgb_hw *hw, uint32_t offset, uint32_t value){ IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, value); return;}/****************************************************************************** * Clears the VLAN filer table * * hw - Struct containing variables accessed by shared code *****************************************************************************/static voidixgb_clear_vfta(struct ixgb_hw *hw){ uint32_t offset; for(offset = 0; offset < IXGB_VLAN_FILTER_TBL_SIZE; offset++) IXGB_WRITE_REG_ARRAY(hw, VFTA, offset, 0); return;}/****************************************************************************** * Configures the flow control settings based on SW configuration. * * hw - Struct containing variables accessed by shared code *****************************************************************************/static boolean_tixgb_setup_fc(struct ixgb_hw *hw){ uint32_t ctrl_reg; uint32_t pap_reg = 0; /* by default, assume no pause time */ boolean_t status = TRUE; DEBUGFUNC("ixgb_setup_fc"); /* Get the current control reg 0 settings */ ctrl_reg = IXGB_READ_REG(hw, CTRL0); /* Clear the Receive Pause Enable and Transmit Pause Enable bits */ ctrl_reg &= ~(IXGB_CTRL0_RPE | IXGB_CTRL0_TPE); /* The possible values of the "flow_control" parameter are: * 0: Flow control is completely disabled * 1: Rx flow control is enabled (we can receive pause frames * but not send pause frames). * 2: Tx flow control is enabled (we can send pause frames * but we do not support receiving pause frames). * 3: Both Rx and TX flow control (symmetric) are enabled. * other: Invalid. */ switch (hw->fc.type) { case ixgb_fc_none: /* 0 */ /* Set CMDC bit to disable Rx Flow control */ ctrl_reg |= (IXGB_CTRL0_CMDC); break; case ixgb_fc_rx_pause: /* 1 */ /* RX Flow control is enabled, and TX Flow control is * disabled. */ ctrl_reg |= (IXGB_CTRL0_RPE); break; case ixgb_fc_tx_pause: /* 2 */ /* TX Flow control is enabled, and RX Flow control is * disabled, by a software over-ride. */ ctrl_reg |= (IXGB_CTRL0_TPE); pap_reg = hw->fc.pause_time; break; case ixgb_fc_full: /* 3 */ /* Flow control (both RX and TX) is enabled by a software * over-ride. */ ctrl_reg |= (IXGB_CTRL0_RPE | IXGB_CTRL0_TPE); pap_reg = hw->fc.pause_time; break; default: /* We should never get here. The value should be 0-3. */ DEBUGOUT("Flow control param set incorrectly\n"); ASSERT(0); break; } /* Write the new settings */ IXGB_WRITE_REG(hw, CTRL0, ctrl_reg); if (pap_reg != 0) { IXGB_WRITE_REG(hw, PAP, pap_reg); } /* Set the flow control receive threshold registers. Normally, * these registers will be set to a default threshold that may be * adjusted later by the driver's runtime code. However, if the * ability to transmit pause frames in not enabled, then these * registers will be set to 0. */ if(!(hw->fc.type & ixgb_fc_tx_pause)) { IXGB_WRITE_REG(hw, FCRTL, 0); IXGB_WRITE_REG(hw, FCRTH, 0); } else { /* We need to set up the Receive Threshold high and low water * marks as well as (optionally) enabling the transmission of XON * frames. */ if(hw->fc.send_xon) { IXGB_WRITE_REG(hw, FCRTL, (hw->fc.low_water | IXGB_FCRTL_XONE)); } else { IXGB_WRITE_REG(hw, FCRTL, hw->fc.low_water); } IXGB_WRITE_REG(hw, FCRTH, hw->fc.high_water); } return (status);}/****************************************************************************** * Reads a word from a device over the Management Data Interface (MDI) bus. * This interface is used to manage Physical layer devices. * * hw - Struct containing variables accessed by hw code * reg_address - Offset of device register being read. * phy_address - Address of device on MDI. * * Returns: Data word (16 bits) from MDI device. * * The 82597EX has support for several MDI access methods. This routine * uses the new protocol MDI Single Command and Address Operation. * This requires that first an address cycle command is sent, followed by a * read command. *****************************************************************************/static uint16_tixgb_read_phy_reg(struct ixgb_hw *hw, uint32_t reg_address, uint32_t phy_address, uint32_t device_type){ uint32_t i; uint32_t data; uint32_t command = 0; ASSERT(reg_address <= IXGB_MAX_PHY_REG_ADDRESS); ASSERT(phy_address <= IXGB_MAX_PHY_ADDRESS); ASSERT(device_type <= IXGB_MAX_PHY_DEV_TYPE); /* Setup and write the address cycle command */ command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) | (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) | (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) | (IXGB_MSCA_ADDR_CYCLE | IXGB_MSCA_MDI_COMMAND)); IXGB_WRITE_REG(hw, MSCA, command); /************************************************************** ** Check every 10 usec to see if the address cycle completed ** The COMMAND bit will clear when the operation is complete. ** This may take as long as 64 usecs (we'll wait 100 usecs max) ** from the CPU Write to the Ready bit assertion. **************************************************************/ for(i = 0; i < 10; i++) { udelay(10); command = IXGB_READ_REG(hw, MSCA); if ((command & IXGB_MSCA_MDI_COMMAND) == 0) break; } ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0); /* Address cycle complete, setup and write the read command */ command = ((reg_address << IXGB_MSCA_NP_ADDR_SHIFT) | (device_type << IXGB_MSCA_DEV_TYPE_SHIFT) | (phy_address << IXGB_MSCA_PHY_ADDR_SHIFT) | (IXGB_MSCA_READ | IXGB_MSCA_MDI_COMMAND)); IXGB_WRITE_REG(hw, MSCA, command); /************************************************************** ** Check every 10 usec to see if the read command completed ** The COMMAND bit will clear when the operation is complete. ** The read may take as long as 64 usecs (we'll wait 100 usecs max) ** from the CPU Write to the Ready bit assertion. **************************************************************/ for(i = 0; i < 10; i++) { udelay(10); command = IXGB_READ_REG(hw, MSCA); if ((command & IXGB_MSCA_MDI_COMMAND) == 0) break; } ASSERT((command & IXGB_MSCA_MDI_COMMAND) == 0); /* Operation is complete, get the data from the MDIO Read/Write Data * register and return. */ data = IXGB_READ_REG(hw, MSRWD); data >>= IXGB_MSRWD_READ_DATA_SHIFT; return((uint16_t) data);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -