network/ether: Import igc from FreeBSD as "intel22x".
This is the driver for Intel's new line of desktop-class ethernet controllers, from FreeBSD. Not yet included in the builds as it is untested. Part of #17212.
This commit is contained in:
@@ -33,5 +33,6 @@ HaikuSubInclude vt612x ;
|
||||
# FreeBSD 13 drivers
|
||||
HaikuSubInclude atheros813x ;
|
||||
HaikuSubInclude broadcom570x ;
|
||||
HaikuSubInclude intel22x ;
|
||||
HaikuSubInclude ipro1000 ;
|
||||
HaikuSubInclude rtl81xx ;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers network ether intel22x ;
|
||||
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_iflib compat ] : true ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : true ;
|
||||
UsePrivateHeaders net system ;
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
UseHeaders [ FDirName $(SUBDIR) ] : true ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev igc ] ;
|
||||
|
||||
SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 _XOPEN_SOURCE ] ;
|
||||
|
||||
KernelAddon intel22x :
|
||||
glue.c
|
||||
if_igc.c
|
||||
igc_api.c
|
||||
igc_base.c
|
||||
igc_i225.c
|
||||
igc_mac.c
|
||||
igc_nvm.c
|
||||
igc_phy.c
|
||||
igc_txrx.c
|
||||
: freebsd_iflib.a libfreebsd_network.a
|
||||
;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,425 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2016 Nicole Graziano <[email protected]>
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_KERNEL_OPTION_HEADERS
|
||||
#include "opt_device_polling.h"
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#ifdef DDB
|
||||
#include <sys/types.h>
|
||||
#include <ddb/ddb.h>
|
||||
#endif
|
||||
#include <sys/buf_ring.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/kthread.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <sys/eventhandler.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/iflib.h>
|
||||
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_vlan_var.h>
|
||||
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include <machine/in_cksum.h>
|
||||
#include <dev/led/led.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
||||
#include "igc_api.h"
|
||||
#include "igc_i225.h"
|
||||
#include "ifdi_if.h"
|
||||
|
||||
|
||||
#ifndef _IGC_H_DEFINED_
|
||||
#define _IGC_H_DEFINED_
|
||||
|
||||
|
||||
/* Tunables */
|
||||
|
||||
/*
|
||||
* IGC_MAX_TXD: Maximum number of Transmit Descriptors
|
||||
* Valid Range: 128-4096
|
||||
* Default Value: 1024
|
||||
* This value is the number of transmit descriptors allocated by the driver.
|
||||
* Increasing this value allows the driver to queue more transmits. Each
|
||||
* descriptor is 16 bytes.
|
||||
* Since TDLEN should be multiple of 128bytes, the number of transmit
|
||||
* desscriptors should meet the following condition.
|
||||
* (num_tx_desc * sizeof(struct igc_tx_desc)) % 128 == 0
|
||||
*/
|
||||
#define IGC_MIN_TXD 128
|
||||
#define IGC_MAX_TXD 4096
|
||||
#define IGC_DEFAULT_TXD 1024
|
||||
#define IGC_DEFAULT_MULTI_TXD 4096
|
||||
#define IGC_MAX_TXD 4096
|
||||
|
||||
/*
|
||||
* IGC_MAX_RXD - Maximum number of receive Descriptors
|
||||
* Valid Range: 128-4096
|
||||
* Default Value: 1024
|
||||
* This value is the number of receive descriptors allocated by the driver.
|
||||
* Increasing this value allows the driver to buffer more incoming packets.
|
||||
* Each descriptor is 16 bytes. A receive buffer is also allocated for each
|
||||
* descriptor. The maximum MTU size is 16110.
|
||||
* Since TDLEN should be multiple of 128bytes, the number of transmit
|
||||
* desscriptors should meet the following condition.
|
||||
* (num_tx_desc * sizeof(struct igc_tx_desc)) % 128 == 0
|
||||
*/
|
||||
#define IGC_MIN_RXD 128
|
||||
#define IGC_MAX_RXD 4096
|
||||
#define IGC_DEFAULT_RXD 1024
|
||||
#define IGC_DEFAULT_MULTI_RXD 4096
|
||||
#define IGC_MAX_RXD 4096
|
||||
|
||||
/*
|
||||
* IGC_TIDV_VAL - Transmit Interrupt Delay Value
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value delays the generation of transmit interrupts in units of
|
||||
* 1.024 microseconds. Transmit interrupt reduction can improve CPU
|
||||
* efficiency if properly tuned for specific network traffic. If the
|
||||
* system is reporting dropped transmits, this value may be set too high
|
||||
* causing the driver to run out of available transmit descriptors.
|
||||
*/
|
||||
#define IGC_TIDV_VAL 64
|
||||
|
||||
/*
|
||||
* IGC_TADV_VAL - Transmit Absolute Interrupt Delay Value
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value, in units of 1.024 microseconds, limits the delay in which a
|
||||
* transmit interrupt is generated. Useful only if IGC_TIDV is non-zero,
|
||||
* this value ensures that an interrupt is generated after the initial
|
||||
* packet is sent on the wire within the set amount of time. Proper tuning,
|
||||
* along with IGC_TIDV_VAL, may improve traffic throughput in specific
|
||||
* network conditions.
|
||||
*/
|
||||
#define IGC_TADV_VAL 64
|
||||
|
||||
/*
|
||||
* IGC_RDTR_VAL - Receive Interrupt Delay Timer (Packet Timer)
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 0
|
||||
* This value delays the generation of receive interrupts in units of 1.024
|
||||
* microseconds. Receive interrupt reduction can improve CPU efficiency if
|
||||
* properly tuned for specific network traffic. Increasing this value adds
|
||||
* extra latency to frame reception and can end up decreasing the throughput
|
||||
* of TCP traffic. If the system is reporting dropped receives, this value
|
||||
* may be set too high, causing the driver to run out of available receive
|
||||
* descriptors.
|
||||
*
|
||||
* CAUTION: When setting IGC_RDTR to a value other than 0, adapters
|
||||
* may hang (stop transmitting) under certain network conditions.
|
||||
* If this occurs a WATCHDOG message is logged in the system
|
||||
* event log. In addition, the controller is automatically reset,
|
||||
* restoring the network connection. To eliminate the potential
|
||||
* for the hang ensure that IGC_RDTR is set to 0.
|
||||
*/
|
||||
#define IGC_RDTR_VAL 0
|
||||
|
||||
/*
|
||||
* Receive Interrupt Absolute Delay Timer
|
||||
* Valid Range: 0-65535 (0=off)
|
||||
* Default Value: 64
|
||||
* This value, in units of 1.024 microseconds, limits the delay in which a
|
||||
* receive interrupt is generated. Useful only if IGC_RDTR is non-zero,
|
||||
* this value ensures that an interrupt is generated after the initial
|
||||
* packet is received within the set amount of time. Proper tuning,
|
||||
* along with IGC_RDTR, may improve traffic throughput in specific network
|
||||
* conditions.
|
||||
*/
|
||||
#define IGC_RADV_VAL 64
|
||||
|
||||
/*
|
||||
* This parameter controls whether or not autonegotation is enabled.
|
||||
* 0 - Disable autonegotiation
|
||||
* 1 - Enable autonegotiation
|
||||
*/
|
||||
#define DO_AUTO_NEG true
|
||||
|
||||
/* Tunables -- End */
|
||||
|
||||
#define AUTONEG_ADV_DEFAULT (ADVERTISE_10_HALF | ADVERTISE_10_FULL | \
|
||||
ADVERTISE_100_HALF | ADVERTISE_100_FULL | \
|
||||
ADVERTISE_1000_FULL | ADVERTISE_2500_FULL)
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
|
||||
/*
|
||||
* Micellaneous constants
|
||||
*/
|
||||
#define MAX_NUM_MULTICAST_ADDRESSES 128
|
||||
#define IGC_FC_PAUSE_TIME 0x0680
|
||||
|
||||
#define IGC_TXPBSIZE 20408
|
||||
#define IGC_PKTTYPE_MASK 0x0000FFF0
|
||||
#define IGC_DMCTLX_DCFLUSH_DIS 0x80000000 /* Disable DMA Coalesce Flush */
|
||||
|
||||
#define IGC_RX_PTHRESH 8
|
||||
#define IGC_RX_HTHRESH 8
|
||||
#define IGC_RX_WTHRESH 4
|
||||
|
||||
#define IGC_TX_PTHRESH 8
|
||||
#define IGC_TX_HTHRESH 1
|
||||
|
||||
/*
|
||||
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
|
||||
* multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
|
||||
* also optimize cache line size effect. H/W supports up to cache line size 128.
|
||||
*/
|
||||
#define IGC_DBA_ALIGN 128
|
||||
|
||||
#define IGC_MSIX_BAR 3
|
||||
|
||||
/* Defines for printing debug information */
|
||||
#define DEBUG_INIT 0
|
||||
#define DEBUG_IOCTL 0
|
||||
#define DEBUG_HW 0
|
||||
|
||||
#define INIT_DEBUGOUT(S) if (DEBUG_INIT) printf(S "\n")
|
||||
#define INIT_DEBUGOUT1(S, A) if (DEBUG_INIT) printf(S "\n", A)
|
||||
#define INIT_DEBUGOUT2(S, A, B) if (DEBUG_INIT) printf(S "\n", A, B)
|
||||
#define IOCTL_DEBUGOUT(S) if (DEBUG_IOCTL) printf(S "\n")
|
||||
#define IOCTL_DEBUGOUT1(S, A) if (DEBUG_IOCTL) printf(S "\n", A)
|
||||
#define IOCTL_DEBUGOUT2(S, A, B) if (DEBUG_IOCTL) printf(S "\n", A, B)
|
||||
#define HW_DEBUGOUT(S) if (DEBUG_HW) printf(S "\n")
|
||||
#define HW_DEBUGOUT1(S, A) if (DEBUG_HW) printf(S "\n", A)
|
||||
#define HW_DEBUGOUT2(S, A, B) if (DEBUG_HW) printf(S "\n", A, B)
|
||||
|
||||
#define IGC_MAX_SCATTER 40
|
||||
#define IGC_VFTA_SIZE 128
|
||||
#define IGC_TSO_SIZE 65535
|
||||
#define IGC_TSO_SEG_SIZE 4096 /* Max dma segment size */
|
||||
#define IGC_CSUM_OFFLOAD (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP | \
|
||||
CSUM_IP_SCTP | CSUM_IP6_UDP | CSUM_IP6_TCP | \
|
||||
CSUM_IP6_SCTP) /* Offload bits in mbuf flag */
|
||||
|
||||
struct igc_adapter;
|
||||
|
||||
struct igc_int_delay_info {
|
||||
struct igc_adapter *adapter; /* Back-pointer to the adapter struct */
|
||||
int offset; /* Register offset to read/write */
|
||||
int value; /* Current value in usecs */
|
||||
};
|
||||
|
||||
/*
|
||||
* The transmit ring, one per tx queue
|
||||
*/
|
||||
struct tx_ring {
|
||||
struct igc_adapter *adapter;
|
||||
struct igc_tx_desc *tx_base;
|
||||
uint64_t tx_paddr;
|
||||
qidx_t *tx_rsq;
|
||||
uint8_t me;
|
||||
qidx_t tx_rs_cidx;
|
||||
qidx_t tx_rs_pidx;
|
||||
qidx_t tx_cidx_processed;
|
||||
/* Interrupt resources */
|
||||
void *tag;
|
||||
struct resource *res;
|
||||
unsigned long tx_irq;
|
||||
|
||||
/* Saved csum offloading context information */
|
||||
int csum_flags;
|
||||
int csum_lhlen;
|
||||
int csum_iphlen;
|
||||
|
||||
int csum_thlen;
|
||||
int csum_mss;
|
||||
int csum_pktlen;
|
||||
|
||||
uint32_t csum_txd_upper;
|
||||
uint32_t csum_txd_lower; /* last field */
|
||||
};
|
||||
|
||||
/*
|
||||
* The Receive ring, one per rx queue
|
||||
*/
|
||||
struct rx_ring {
|
||||
struct igc_adapter *adapter;
|
||||
struct igc_rx_queue *que;
|
||||
u32 me;
|
||||
u32 payload;
|
||||
union igc_rx_desc_extended *rx_base;
|
||||
uint64_t rx_paddr;
|
||||
|
||||
/* Interrupt resources */
|
||||
void *tag;
|
||||
struct resource *res;
|
||||
|
||||
/* Soft stats */
|
||||
unsigned long rx_irq;
|
||||
unsigned long rx_discarded;
|
||||
unsigned long rx_packets;
|
||||
unsigned long rx_bytes;
|
||||
};
|
||||
|
||||
struct igc_tx_queue {
|
||||
struct igc_adapter *adapter;
|
||||
u32 msix;
|
||||
u32 eims; /* This queue's EIMS bit */
|
||||
u32 me;
|
||||
struct tx_ring txr;
|
||||
};
|
||||
|
||||
struct igc_rx_queue {
|
||||
struct igc_adapter *adapter;
|
||||
u32 me;
|
||||
u32 msix;
|
||||
u32 eims;
|
||||
struct rx_ring rxr;
|
||||
u64 irqs;
|
||||
struct if_irq que_irq;
|
||||
};
|
||||
|
||||
/* Our adapter structure */
|
||||
struct igc_adapter {
|
||||
struct ifnet *ifp;
|
||||
struct igc_hw hw;
|
||||
|
||||
if_softc_ctx_t shared;
|
||||
if_ctx_t ctx;
|
||||
#define tx_num_queues shared->isc_ntxqsets
|
||||
#define rx_num_queues shared->isc_nrxqsets
|
||||
#define intr_type shared->isc_intr
|
||||
/* FreeBSD operating-system-specific structures. */
|
||||
struct igc_osdep osdep;
|
||||
device_t dev;
|
||||
struct cdev *led_dev;
|
||||
|
||||
struct igc_tx_queue *tx_queues;
|
||||
struct igc_rx_queue *rx_queues;
|
||||
struct if_irq irq;
|
||||
|
||||
struct resource *memory;
|
||||
struct resource *flash;
|
||||
struct resource *ioport;
|
||||
|
||||
struct resource *res;
|
||||
void *tag;
|
||||
u32 linkvec;
|
||||
u32 ivars;
|
||||
|
||||
struct ifmedia *media;
|
||||
int msix;
|
||||
int if_flags;
|
||||
int igc_insert_vlan_header;
|
||||
u32 ims;
|
||||
|
||||
u32 flags;
|
||||
/* Task for FAST handling */
|
||||
struct grouptask link_task;
|
||||
|
||||
u16 num_vlans;
|
||||
u32 txd_cmd;
|
||||
|
||||
u32 tx_process_limit;
|
||||
u32 rx_process_limit;
|
||||
u32 rx_mbuf_sz;
|
||||
|
||||
/* Management and WOL features */
|
||||
u32 wol;
|
||||
|
||||
/* Multicast array memory */
|
||||
u8 *mta;
|
||||
|
||||
/*
|
||||
** Shadow VFTA table, this is needed because
|
||||
** the real vlan filter table gets cleared during
|
||||
** a soft reset and the driver needs to be able
|
||||
** to repopulate it.
|
||||
*/
|
||||
u32 shadow_vfta[IGC_VFTA_SIZE];
|
||||
|
||||
/* Info about the interface */
|
||||
u16 link_active;
|
||||
u16 fc;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
u32 smartspeed;
|
||||
u32 dmac;
|
||||
int link_mask;
|
||||
|
||||
u64 que_mask;
|
||||
|
||||
struct igc_int_delay_info tx_int_delay;
|
||||
struct igc_int_delay_info tx_abs_int_delay;
|
||||
struct igc_int_delay_info rx_int_delay;
|
||||
struct igc_int_delay_info rx_abs_int_delay;
|
||||
struct igc_int_delay_info tx_itr;
|
||||
|
||||
/* Misc stats maintained by the driver */
|
||||
unsigned long dropped_pkts;
|
||||
unsigned long link_irq;
|
||||
unsigned long rx_overruns;
|
||||
unsigned long watchdog_events;
|
||||
|
||||
struct igc_hw_stats stats;
|
||||
u16 vf_ifp;
|
||||
};
|
||||
|
||||
void igc_dump_rs(struct igc_adapter *);
|
||||
|
||||
#define IGC_RSSRK_SIZE 4
|
||||
#define IGC_RSSRK_VAL(key, i) (key[(i) * IGC_RSSRK_SIZE] | \
|
||||
key[(i) * IGC_RSSRK_SIZE + 1] << 8 | \
|
||||
key[(i) * IGC_RSSRK_SIZE + 2] << 16 | \
|
||||
key[(i) * IGC_RSSRK_SIZE + 3] << 24)
|
||||
#endif /* _IGC_H_DEFINED_ */
|
||||
@@ -0,0 +1,735 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "igc_api.h"
|
||||
|
||||
/**
|
||||
* igc_init_mac_params - Initialize MAC function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This function initializes the function pointers for the MAC
|
||||
* set of functions. Called by drivers or by igc_setup_init_funcs.
|
||||
**/
|
||||
s32 igc_init_mac_params(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val = IGC_SUCCESS;
|
||||
|
||||
if (hw->mac.ops.init_params) {
|
||||
ret_val = hw->mac.ops.init_params(hw);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("MAC Initialization Error\n");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
DEBUGOUT("mac.init_mac_params was NULL\n");
|
||||
ret_val = -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_nvm_params - Initialize NVM function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This function initializes the function pointers for the NVM
|
||||
* set of functions. Called by drivers or by igc_setup_init_funcs.
|
||||
**/
|
||||
s32 igc_init_nvm_params(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val = IGC_SUCCESS;
|
||||
|
||||
if (hw->nvm.ops.init_params) {
|
||||
ret_val = hw->nvm.ops.init_params(hw);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Initialization Error\n");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
DEBUGOUT("nvm.init_nvm_params was NULL\n");
|
||||
ret_val = -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_phy_params - Initialize PHY function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This function initializes the function pointers for the PHY
|
||||
* set of functions. Called by drivers or by igc_setup_init_funcs.
|
||||
**/
|
||||
s32 igc_init_phy_params(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val = IGC_SUCCESS;
|
||||
|
||||
if (hw->phy.ops.init_params) {
|
||||
ret_val = hw->phy.ops.init_params(hw);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("PHY Initialization Error\n");
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
DEBUGOUT("phy.init_phy_params was NULL\n");
|
||||
ret_val = -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_set_mac_type - Sets MAC type
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This function sets the mac type of the adapter based on the
|
||||
* device ID stored in the hw structure.
|
||||
* MUST BE FIRST FUNCTION CALLED (explicitly or through
|
||||
* igc_setup_init_funcs()).
|
||||
**/
|
||||
s32 igc_set_mac_type(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = IGC_SUCCESS;
|
||||
|
||||
DEBUGFUNC("igc_set_mac_type");
|
||||
|
||||
switch (hw->device_id) {
|
||||
case IGC_DEV_ID_I225_LM:
|
||||
case IGC_DEV_ID_I225_V:
|
||||
case IGC_DEV_ID_I225_K:
|
||||
case IGC_DEV_ID_I225_I:
|
||||
case IGC_DEV_ID_I220_V:
|
||||
case IGC_DEV_ID_I225_K2:
|
||||
case IGC_DEV_ID_I225_LMVP:
|
||||
case IGC_DEV_ID_I225_IT:
|
||||
case IGC_DEV_ID_I226_LM:
|
||||
case IGC_DEV_ID_I226_V:
|
||||
case IGC_DEV_ID_I226_IT:
|
||||
case IGC_DEV_ID_I221_V:
|
||||
case IGC_DEV_ID_I226_BLANK_NVM:
|
||||
case IGC_DEV_ID_I225_BLANK_NVM:
|
||||
mac->type = igc_i225;
|
||||
break;
|
||||
default:
|
||||
/* Should never have loaded on this device */
|
||||
ret_val = -IGC_ERR_MAC_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_setup_init_funcs - Initializes function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
* @init_device: true will initialize the rest of the function pointers
|
||||
* getting the device ready for use. FALSE will only set
|
||||
* MAC type and the function pointers for the other init
|
||||
* functions. Passing FALSE will not generate any hardware
|
||||
* reads or writes.
|
||||
*
|
||||
* This function must be called by a driver in order to use the rest
|
||||
* of the 'shared' code files. Called by drivers only.
|
||||
**/
|
||||
s32 igc_setup_init_funcs(struct igc_hw *hw, bool init_device)
|
||||
{
|
||||
s32 ret_val;
|
||||
|
||||
/* Can't do much good without knowing the MAC type. */
|
||||
ret_val = igc_set_mac_type(hw);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("ERROR: MAC type could not be set properly.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!hw->hw_addr) {
|
||||
DEBUGOUT("ERROR: Registers not mapped\n");
|
||||
ret_val = -IGC_ERR_CONFIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Init function pointers to generic implementations. We do this first
|
||||
* allowing a driver module to override it afterward.
|
||||
*/
|
||||
igc_init_mac_ops_generic(hw);
|
||||
igc_init_phy_ops_generic(hw);
|
||||
igc_init_nvm_ops_generic(hw);
|
||||
|
||||
/*
|
||||
* Set up the init function pointers. These are functions within the
|
||||
* adapter family file that sets up function pointers for the rest of
|
||||
* the functions in that family.
|
||||
*/
|
||||
switch (hw->mac.type) {
|
||||
case igc_i225:
|
||||
igc_init_function_pointers_i225(hw);
|
||||
break;
|
||||
default:
|
||||
DEBUGOUT("Hardware not supported\n");
|
||||
ret_val = -IGC_ERR_CONFIG;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the rest of the function pointers. These require some
|
||||
* register reads/writes in some cases.
|
||||
*/
|
||||
if (!(ret_val) && init_device) {
|
||||
ret_val = igc_init_mac_params(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = igc_init_nvm_params(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
ret_val = igc_init_phy_params(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_get_bus_info - Obtain bus information for adapter
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This will obtain information about the HW bus for which the
|
||||
* adapter is attached and stores it in the hw structure. This is a
|
||||
* function pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_get_bus_info(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.get_bus_info)
|
||||
return hw->mac.ops.get_bus_info(hw);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_clear_vfta - Clear VLAN filter table
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This clears the VLAN filter table on the adapter. This is a function
|
||||
* pointer entry point called by drivers.
|
||||
**/
|
||||
void igc_clear_vfta(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.clear_vfta)
|
||||
hw->mac.ops.clear_vfta(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_write_vfta - Write value to VLAN filter table
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: the 32-bit offset in which to write the value to.
|
||||
* @value: the 32-bit value to write at location offset.
|
||||
*
|
||||
* This writes a 32-bit value to a 32-bit offset in the VLAN filter
|
||||
* table. This is a function pointer entry point called by drivers.
|
||||
**/
|
||||
void igc_write_vfta(struct igc_hw *hw, u32 offset, u32 value)
|
||||
{
|
||||
if (hw->mac.ops.write_vfta)
|
||||
hw->mac.ops.write_vfta(hw, offset, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_update_mc_addr_list - Update Multicast addresses
|
||||
* @hw: pointer to the HW structure
|
||||
* @mc_addr_list: array of multicast addresses to program
|
||||
* @mc_addr_count: number of multicast addresses to program
|
||||
*
|
||||
* Updates the Multicast Table Array.
|
||||
* The caller must have a packed mc_addr_list of multicast addresses.
|
||||
**/
|
||||
void igc_update_mc_addr_list(struct igc_hw *hw, u8 *mc_addr_list,
|
||||
u32 mc_addr_count)
|
||||
{
|
||||
if (hw->mac.ops.update_mc_addr_list)
|
||||
hw->mac.ops.update_mc_addr_list(hw, mc_addr_list,
|
||||
mc_addr_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_force_mac_fc - Force MAC flow control
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Force the MAC's flow control settings. Currently no func pointer exists
|
||||
* and all implementations are handled in the generic version of this
|
||||
* function.
|
||||
**/
|
||||
s32 igc_force_mac_fc(struct igc_hw *hw)
|
||||
{
|
||||
return igc_force_mac_fc_generic(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_check_for_link - Check/Store link connection
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This checks the link condition of the adapter and stores the
|
||||
* results in the hw->mac structure. This is a function pointer entry
|
||||
* point called by drivers.
|
||||
**/
|
||||
s32 igc_check_for_link(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.check_for_link)
|
||||
return hw->mac.ops.check_for_link(hw);
|
||||
|
||||
return -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_reset_hw - Reset hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This resets the hardware into a known state. This is a function pointer
|
||||
* entry point called by drivers.
|
||||
**/
|
||||
s32 igc_reset_hw(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.reset_hw)
|
||||
return hw->mac.ops.reset_hw(hw);
|
||||
|
||||
return -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_hw - Initialize hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This inits the hardware readying it for operation. This is a function
|
||||
* pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_init_hw(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.init_hw)
|
||||
return hw->mac.ops.init_hw(hw);
|
||||
|
||||
return -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_setup_link - Configures link and flow control
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This configures link and flow control settings for the adapter. This
|
||||
* is a function pointer entry point called by drivers. While modules can
|
||||
* also call this, they probably call their own version of this function.
|
||||
**/
|
||||
s32 igc_setup_link(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.setup_link)
|
||||
return hw->mac.ops.setup_link(hw);
|
||||
|
||||
return -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_get_speed_and_duplex - Returns current speed and duplex
|
||||
* @hw: pointer to the HW structure
|
||||
* @speed: pointer to a 16-bit value to store the speed
|
||||
* @duplex: pointer to a 16-bit value to store the duplex.
|
||||
*
|
||||
* This returns the speed and duplex of the adapter in the two 'out'
|
||||
* variables passed in. This is a function pointer entry point called
|
||||
* by drivers.
|
||||
**/
|
||||
s32 igc_get_speed_and_duplex(struct igc_hw *hw, u16 *speed, u16 *duplex)
|
||||
{
|
||||
if (hw->mac.ops.get_link_up_info)
|
||||
return hw->mac.ops.get_link_up_info(hw, speed, duplex);
|
||||
|
||||
return -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_disable_pcie_master - Disable PCI-Express master access
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Disables PCI-Express master access and verifies there are no pending
|
||||
* requests. Currently no func pointer exists and all implementations are
|
||||
* handled in the generic version of this function.
|
||||
**/
|
||||
s32 igc_disable_pcie_master(struct igc_hw *hw)
|
||||
{
|
||||
return igc_disable_pcie_master_generic(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_config_collision_dist - Configure collision distance
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Configures the collision distance to the default value and is used
|
||||
* during link setup.
|
||||
**/
|
||||
void igc_config_collision_dist(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.config_collision_dist)
|
||||
hw->mac.ops.config_collision_dist(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_rar_set - Sets a receive address register
|
||||
* @hw: pointer to the HW structure
|
||||
* @addr: address to set the RAR to
|
||||
* @index: the RAR to set
|
||||
*
|
||||
* Sets a Receive Address Register (RAR) to the specified address.
|
||||
**/
|
||||
int igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index)
|
||||
{
|
||||
if (hw->mac.ops.rar_set)
|
||||
return hw->mac.ops.rar_set(hw, addr, index);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_validate_mdi_setting - Ensures valid MDI/MDIX SW state
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Ensures that the MDI/MDIX SW state is valid.
|
||||
**/
|
||||
s32 igc_validate_mdi_setting(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.validate_mdi_setting)
|
||||
return hw->mac.ops.validate_mdi_setting(hw);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_hash_mc_addr - Determines address location in multicast table
|
||||
* @hw: pointer to the HW structure
|
||||
* @mc_addr: Multicast address to hash.
|
||||
*
|
||||
* This hashes an address to determine its location in the multicast
|
||||
* table. Currently no func pointer exists and all implementations
|
||||
* are handled in the generic version of this function.
|
||||
**/
|
||||
u32 igc_hash_mc_addr(struct igc_hw *hw, u8 *mc_addr)
|
||||
{
|
||||
return igc_hash_mc_addr_generic(hw, mc_addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_check_reset_block - Verifies PHY can be reset
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Checks if the PHY is in a state that can be reset or if manageability
|
||||
* has it tied up. This is a function pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_check_reset_block(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.check_reset_block)
|
||||
return hw->phy.ops.check_reset_block(hw);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_read_phy_reg - Reads PHY register
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: the register to read
|
||||
* @data: the buffer to store the 16-bit read.
|
||||
*
|
||||
* Reads the PHY register and returns the value in data.
|
||||
* This is a function pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
|
||||
{
|
||||
if (hw->phy.ops.read_reg)
|
||||
return hw->phy.ops.read_reg(hw, offset, data);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_write_phy_reg - Writes PHY register
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: the register to write
|
||||
* @data: the value to write.
|
||||
*
|
||||
* Writes the PHY register at offset with the value in data.
|
||||
* This is a function pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_write_phy_reg(struct igc_hw *hw, u32 offset, u16 data)
|
||||
{
|
||||
if (hw->phy.ops.write_reg)
|
||||
return hw->phy.ops.write_reg(hw, offset, data);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_release_phy - Generic release PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Return if silicon family does not require a semaphore when accessing the
|
||||
* PHY.
|
||||
**/
|
||||
void igc_release_phy(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.release)
|
||||
hw->phy.ops.release(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_acquire_phy - Generic acquire PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Return success if silicon family does not require a semaphore when
|
||||
* accessing the PHY.
|
||||
**/
|
||||
s32 igc_acquire_phy(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.acquire)
|
||||
return hw->phy.ops.acquire(hw);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_get_phy_info - Retrieves PHY information from registers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This function gets some information from various PHY registers and
|
||||
* populates hw->phy values with it. This is a function pointer entry
|
||||
* point called by drivers.
|
||||
**/
|
||||
s32 igc_get_phy_info(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.get_info)
|
||||
return hw->phy.ops.get_info(hw);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_phy_hw_reset - Hard PHY reset
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Performs a hard PHY reset. This is a function pointer entry point called
|
||||
* by drivers.
|
||||
**/
|
||||
s32 igc_phy_hw_reset(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.reset)
|
||||
return hw->phy.ops.reset(hw);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_phy_commit - Soft PHY reset
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Performs a soft PHY reset on those that apply. This is a function pointer
|
||||
* entry point called by drivers.
|
||||
**/
|
||||
s32 igc_phy_commit(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.commit)
|
||||
return hw->phy.ops.commit(hw);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_set_d0_lplu_state - Sets low power link up state for D0
|
||||
* @hw: pointer to the HW structure
|
||||
* @active: boolean used to enable/disable lplu
|
||||
*
|
||||
* Success returns 0, Failure returns 1
|
||||
*
|
||||
* The low power link up (lplu) state is set to the power management level D0
|
||||
* and SmartSpeed is disabled when active is true, else clear lplu for D0
|
||||
* and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
|
||||
* is used during Dx states where the power conservation is most important.
|
||||
* During driver activity, SmartSpeed should be enabled so performance is
|
||||
* maintained. This is a function pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_set_d0_lplu_state(struct igc_hw *hw, bool active)
|
||||
{
|
||||
if (hw->phy.ops.set_d0_lplu_state)
|
||||
return hw->phy.ops.set_d0_lplu_state(hw, active);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_set_d3_lplu_state - Sets low power link up state for D3
|
||||
* @hw: pointer to the HW structure
|
||||
* @active: boolean used to enable/disable lplu
|
||||
*
|
||||
* Success returns 0, Failure returns 1
|
||||
*
|
||||
* The low power link up (lplu) state is set to the power management level D3
|
||||
* and SmartSpeed is disabled when active is true, else clear lplu for D3
|
||||
* and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
|
||||
* is used during Dx states where the power conservation is most important.
|
||||
* During driver activity, SmartSpeed should be enabled so performance is
|
||||
* maintained. This is a function pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_set_d3_lplu_state(struct igc_hw *hw, bool active)
|
||||
{
|
||||
if (hw->phy.ops.set_d3_lplu_state)
|
||||
return hw->phy.ops.set_d3_lplu_state(hw, active);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_read_mac_addr - Reads MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reads the MAC address out of the adapter and stores it in the HW structure.
|
||||
* Currently no func pointer exists and all implementations are handled in the
|
||||
* generic version of this function.
|
||||
**/
|
||||
s32 igc_read_mac_addr(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->mac.ops.read_mac_addr)
|
||||
return hw->mac.ops.read_mac_addr(hw);
|
||||
|
||||
return igc_read_mac_addr_generic(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_read_pba_string - Read device part number string
|
||||
* @hw: pointer to the HW structure
|
||||
* @pba_num: pointer to device part number
|
||||
* @pba_num_size: size of part number buffer
|
||||
*
|
||||
* Reads the product board assembly (PBA) number from the EEPROM and stores
|
||||
* the value in pba_num.
|
||||
* Currently no func pointer exists and all implementations are handled in the
|
||||
* generic version of this function.
|
||||
**/
|
||||
s32 igc_read_pba_string(struct igc_hw *hw, u8 *pba_num, u32 pba_num_size)
|
||||
{
|
||||
return igc_read_pba_string_generic(hw, pba_num, pba_num_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_validate_nvm_checksum - Verifies NVM (EEPROM) checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Validates the NVM checksum is correct. This is a function pointer entry
|
||||
* point called by drivers.
|
||||
**/
|
||||
s32 igc_validate_nvm_checksum(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->nvm.ops.validate)
|
||||
return hw->nvm.ops.validate(hw);
|
||||
|
||||
return -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_update_nvm_checksum - Updates NVM (EEPROM) checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Updates the NVM checksum. Currently no func pointer exists and all
|
||||
* implementations are handled in the generic version of this function.
|
||||
**/
|
||||
s32 igc_update_nvm_checksum(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->nvm.ops.update)
|
||||
return hw->nvm.ops.update(hw);
|
||||
|
||||
return -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_reload_nvm - Reloads EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
|
||||
* extended control register.
|
||||
**/
|
||||
void igc_reload_nvm(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->nvm.ops.reload)
|
||||
hw->nvm.ops.reload(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_read_nvm - Reads NVM (EEPROM)
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: the word offset to read
|
||||
* @words: number of 16-bit words to read
|
||||
* @data: pointer to the properly sized buffer for the data.
|
||||
*
|
||||
* Reads 16-bit chunks of data from the NVM (EEPROM). This is a function
|
||||
* pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_read_nvm(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
if (hw->nvm.ops.read)
|
||||
return hw->nvm.ops.read(hw, offset, words, data);
|
||||
|
||||
return -IGC_ERR_CONFIG;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_write_nvm - Writes to NVM (EEPROM)
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: the word offset to read
|
||||
* @words: number of 16-bit words to write
|
||||
* @data: pointer to the properly sized buffer for the data.
|
||||
*
|
||||
* Writes 16-bit chunks of data to the NVM (EEPROM). This is a function
|
||||
* pointer entry point called by drivers.
|
||||
**/
|
||||
s32 igc_write_nvm(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
if (hw->nvm.ops.write)
|
||||
return hw->nvm.ops.write(hw, offset, words, data);
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_power_up_phy - Restores link in case of PHY power down
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* The phy may be powered down to save power, to turn off link when the
|
||||
* driver is unloaded, or wake on lan is not enabled (among others).
|
||||
**/
|
||||
void igc_power_up_phy(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.power_up)
|
||||
hw->phy.ops.power_up(hw);
|
||||
|
||||
igc_setup_link(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_power_down_phy - Power down PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* The phy may be powered down to save power, to turn off link when the
|
||||
* driver is unloaded, or wake on lan is not enabled (among others).
|
||||
**/
|
||||
void igc_power_down_phy(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.power_down)
|
||||
hw->phy.ops.power_down(hw);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IGC_API_H_
|
||||
#define _IGC_API_H_
|
||||
|
||||
#include "igc_hw.h"
|
||||
|
||||
extern void igc_init_function_pointers_i225(struct igc_hw *hw);
|
||||
|
||||
s32 igc_set_mac_type(struct igc_hw *hw);
|
||||
s32 igc_setup_init_funcs(struct igc_hw *hw, bool init_device);
|
||||
s32 igc_init_mac_params(struct igc_hw *hw);
|
||||
s32 igc_init_nvm_params(struct igc_hw *hw);
|
||||
s32 igc_init_phy_params(struct igc_hw *hw);
|
||||
s32 igc_get_bus_info(struct igc_hw *hw);
|
||||
void igc_clear_vfta(struct igc_hw *hw);
|
||||
void igc_write_vfta(struct igc_hw *hw, u32 offset, u32 value);
|
||||
s32 igc_force_mac_fc(struct igc_hw *hw);
|
||||
s32 igc_check_for_link(struct igc_hw *hw);
|
||||
s32 igc_reset_hw(struct igc_hw *hw);
|
||||
s32 igc_init_hw(struct igc_hw *hw);
|
||||
s32 igc_setup_link(struct igc_hw *hw);
|
||||
s32 igc_get_speed_and_duplex(struct igc_hw *hw, u16 *speed, u16 *duplex);
|
||||
s32 igc_disable_pcie_master(struct igc_hw *hw);
|
||||
void igc_config_collision_dist(struct igc_hw *hw);
|
||||
int igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index);
|
||||
u32 igc_hash_mc_addr(struct igc_hw *hw, u8 *mc_addr);
|
||||
void igc_update_mc_addr_list(struct igc_hw *hw, u8 *mc_addr_list,
|
||||
u32 mc_addr_count);
|
||||
s32 igc_check_reset_block(struct igc_hw *hw);
|
||||
s32 igc_get_cable_length(struct igc_hw *hw);
|
||||
s32 igc_validate_mdi_setting(struct igc_hw *hw);
|
||||
s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data);
|
||||
s32 igc_write_phy_reg(struct igc_hw *hw, u32 offset, u16 data);
|
||||
s32 igc_get_phy_info(struct igc_hw *hw);
|
||||
void igc_release_phy(struct igc_hw *hw);
|
||||
s32 igc_acquire_phy(struct igc_hw *hw);
|
||||
s32 igc_phy_hw_reset(struct igc_hw *hw);
|
||||
s32 igc_phy_commit(struct igc_hw *hw);
|
||||
void igc_power_up_phy(struct igc_hw *hw);
|
||||
void igc_power_down_phy(struct igc_hw *hw);
|
||||
s32 igc_read_mac_addr(struct igc_hw *hw);
|
||||
s32 igc_read_pba_string(struct igc_hw *hw, u8 *pba_num, u32 pba_num_size);
|
||||
void igc_reload_nvm(struct igc_hw *hw);
|
||||
s32 igc_update_nvm_checksum(struct igc_hw *hw);
|
||||
s32 igc_validate_nvm_checksum(struct igc_hw *hw);
|
||||
s32 igc_read_nvm(struct igc_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 igc_write_nvm(struct igc_hw *hw, u16 offset, u16 words, u16 *data);
|
||||
s32 igc_set_d3_lplu_state(struct igc_hw *hw, bool active);
|
||||
s32 igc_set_d0_lplu_state(struct igc_hw *hw, bool active);
|
||||
|
||||
#endif /* _IGC_API_H_ */
|
||||
@@ -0,0 +1,188 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "igc_hw.h"
|
||||
#include "igc_i225.h"
|
||||
#include "igc_mac.h"
|
||||
#include "igc_base.h"
|
||||
|
||||
/**
|
||||
* igc_acquire_phy_base - Acquire rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire access rights to the correct PHY.
|
||||
**/
|
||||
s32 igc_acquire_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
DEBUGFUNC("igc_acquire_phy_base");
|
||||
|
||||
if (hw->bus.func == IGC_FUNC_1)
|
||||
mask = IGC_SWFW_PHY1_SM;
|
||||
|
||||
return hw->mac.ops.acquire_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_release_phy_base - Release rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* A wrapper to release access rights to the correct PHY.
|
||||
**/
|
||||
void igc_release_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
DEBUGFUNC("igc_release_phy_base");
|
||||
|
||||
if (hw->bus.func == IGC_FUNC_1)
|
||||
mask = IGC_SWFW_PHY1_SM;
|
||||
|
||||
hw->mac.ops.release_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_hw_base - Initialize hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This inits the hardware readying it for operation.
|
||||
**/
|
||||
s32 igc_init_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
s32 ret_val;
|
||||
u16 i, rar_count = mac->rar_entry_count;
|
||||
|
||||
DEBUGFUNC("igc_init_hw_base");
|
||||
|
||||
/* Setup the receive address */
|
||||
igc_init_rx_addrs_generic(hw, rar_count);
|
||||
|
||||
/* Zero out the Multicast HASH table */
|
||||
DEBUGOUT("Zeroing the MTA\n");
|
||||
for (i = 0; i < mac->mta_reg_count; i++)
|
||||
IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
|
||||
|
||||
/* Zero out the Unicast HASH table */
|
||||
DEBUGOUT("Zeroing the UTA\n");
|
||||
for (i = 0; i < mac->uta_reg_count; i++)
|
||||
IGC_WRITE_REG_ARRAY(hw, IGC_UTA, i, 0);
|
||||
|
||||
/* Setup link and flow control */
|
||||
ret_val = mac->ops.setup_link(hw);
|
||||
/*
|
||||
* Clear all of the statistics registers (clear on read). It is
|
||||
* important that we do this after we have tried to establish link
|
||||
* because the symbol error count will increment wildly if there
|
||||
* is no link.
|
||||
*/
|
||||
igc_clear_hw_cntrs_base_generic(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_power_down_phy_copper_base - Remove link during PHY power down
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* In the case of a PHY power down to save power, or to turn off link during a
|
||||
* driver unload, or wake on lan is not enabled, remove the link.
|
||||
**/
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_phy_info *phy = &hw->phy;
|
||||
|
||||
if (!(phy->ops.check_reset_block))
|
||||
return;
|
||||
|
||||
/* If the management interface is not enabled, then power down */
|
||||
if (phy->ops.check_reset_block(hw))
|
||||
igc_power_down_phy_copper(hw);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_rx_fifo_flush_base - Clean Rx FIFO after Rx enable
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* After Rx enable, if manageability is enabled then there is likely some
|
||||
* bad data at the start of the FIFO and possibly in the DMA FIFO. This
|
||||
* function clears the FIFOs and flushes any packets that came in as Rx was
|
||||
* being enabled.
|
||||
**/
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw)
|
||||
{
|
||||
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
|
||||
int i, ms_wait;
|
||||
|
||||
DEBUGFUNC("igc_rx_fifo_flush_base");
|
||||
|
||||
/* disable IPv6 options as per hardware errata */
|
||||
rfctl = IGC_READ_REG(hw, IGC_RFCTL);
|
||||
rfctl |= IGC_RFCTL_IPV6_EX_DIS;
|
||||
IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
|
||||
|
||||
if (!(IGC_READ_REG(hw, IGC_MANC) & IGC_MANC_RCV_TCO_EN))
|
||||
return;
|
||||
|
||||
/* Disable all Rx queues */
|
||||
for (i = 0; i < 4; i++) {
|
||||
rxdctl[i] = IGC_READ_REG(hw, IGC_RXDCTL(i));
|
||||
IGC_WRITE_REG(hw, IGC_RXDCTL(i),
|
||||
rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE);
|
||||
}
|
||||
/* Poll all queues to verify they have shut down */
|
||||
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
|
||||
msec_delay(1);
|
||||
rx_enabled = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
rx_enabled |= IGC_READ_REG(hw, IGC_RXDCTL(i));
|
||||
if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ms_wait == 10)
|
||||
DEBUGOUT("Queue disable timed out after 10ms\n");
|
||||
|
||||
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
|
||||
* incoming packets are rejected. Set enable and wait 2ms so that
|
||||
* any packet that was coming in as RCTL.EN was set is flushed
|
||||
*/
|
||||
IGC_WRITE_REG(hw, IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF);
|
||||
|
||||
rlpml = IGC_READ_REG(hw, IGC_RLPML);
|
||||
IGC_WRITE_REG(hw, IGC_RLPML, 0);
|
||||
|
||||
rctl = IGC_READ_REG(hw, IGC_RCTL);
|
||||
temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP);
|
||||
temp_rctl |= IGC_RCTL_LPE;
|
||||
|
||||
IGC_WRITE_REG(hw, IGC_RCTL, temp_rctl);
|
||||
IGC_WRITE_REG(hw, IGC_RCTL, temp_rctl | IGC_RCTL_EN);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
msec_delay(2);
|
||||
|
||||
/* Enable Rx queues that were previously enabled and restore our
|
||||
* previous state
|
||||
*/
|
||||
for (i = 0; i < 4; i++)
|
||||
IGC_WRITE_REG(hw, IGC_RXDCTL(i), rxdctl[i]);
|
||||
IGC_WRITE_REG(hw, IGC_RCTL, rctl);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
|
||||
IGC_WRITE_REG(hw, IGC_RLPML, rlpml);
|
||||
IGC_WRITE_REG(hw, IGC_RFCTL, rfctl);
|
||||
|
||||
/* Flush receive errors generated by workaround */
|
||||
IGC_READ_REG(hw, IGC_ROC);
|
||||
IGC_READ_REG(hw, IGC_RNBC);
|
||||
IGC_READ_REG(hw, IGC_MPC);
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IGC_BASE_H_
|
||||
#define _IGC_BASE_H_
|
||||
|
||||
/* forward declaration */
|
||||
s32 igc_init_hw_base(struct igc_hw *hw);
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw);
|
||||
extern void igc_rx_fifo_flush_base(struct igc_hw *hw);
|
||||
s32 igc_acquire_phy_base(struct igc_hw *hw);
|
||||
void igc_release_phy_base(struct igc_hw *hw);
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union igc_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Context descriptors */
|
||||
struct igc_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
union {
|
||||
__le32 launch_time;
|
||||
__le32 seqnum_seed;
|
||||
};
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define IGC_ADVTXD_DCMD_DDTYP_ISCSI 0x10000000 /* DDP hdr type or iSCSI */
|
||||
#define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define IGC_ADVTXD_MAC_LINKSEC 0x00040000 /* Apply LinkSec on pkt */
|
||||
#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp pkt */
|
||||
#define IGC_ADVTXD_STAT_SN_CRC 0x00000002 /* NXTSEQ/SEED prsnt in WB */
|
||||
#define IGC_ADVTXD_IDX_SHIFT 4 /* Adv desc Index shift */
|
||||
#define IGC_ADVTXD_POPTS_ISCO_1ST 0x00000000 /* 1st TSO of iSCSI PDU */
|
||||
#define IGC_ADVTXD_POPTS_ISCO_MDL 0x00000800 /* Middle TSO of iSCSI PDU */
|
||||
#define IGC_ADVTXD_POPTS_ISCO_LAST 0x00001000 /* Last TSO of iSCSI PDU */
|
||||
/* 1st & Last TSO-full iSCSI PDU*/
|
||||
#define IGC_ADVTXD_POPTS_ISCO_FULL 0x00001800
|
||||
#define IGC_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */
|
||||
#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Advanced Transmit Context Descriptor Config */
|
||||
#define IGC_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define IGC_ADVTXD_VLAN_SHIFT 16 /* Adv ctxt vlan tag shift */
|
||||
#define IGC_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define IGC_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
|
||||
#define IGC_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
|
||||
/* IPSec Encrypt Enable for ESP */
|
||||
#define IGC_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000
|
||||
/* Req requires Markers and CRC */
|
||||
#define IGC_ADVTXD_TUCMD_MKRREQ 0x00002000
|
||||
#define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
/* Adv ctxt IPSec SA IDX mask */
|
||||
#define IGC_ADVTXD_IPSEC_SA_INDEX_MASK 0x000000FF
|
||||
/* Adv ctxt IPSec ESP len mask */
|
||||
#define IGC_ADVTXD_IPSEC_ESP_LEN_MASK 0x000000FF
|
||||
|
||||
#define IGC_RAR_ENTRIES_BASE 16
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union igc_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
__le16 pkt_info; /*RSS type, Pkt type*/
|
||||
/* Split Header, header buffer len */
|
||||
__le16 hdr_info;
|
||||
} hs_rss;
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
|
||||
#endif /* _IGC_BASE_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,548 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IGC_HW_H_
|
||||
#define _IGC_HW_H_
|
||||
|
||||
#include "igc_osdep.h"
|
||||
#include "igc_regs.h"
|
||||
#include "igc_defines.h"
|
||||
|
||||
struct igc_hw;
|
||||
|
||||
#define IGC_DEV_ID_I225_LM 0x15F2
|
||||
#define IGC_DEV_ID_I225_V 0x15F3
|
||||
#define IGC_DEV_ID_I225_K 0x3100
|
||||
#define IGC_DEV_ID_I225_I 0x15F8
|
||||
#define IGC_DEV_ID_I220_V 0x15F7
|
||||
#define IGC_DEV_ID_I225_K2 0x3101
|
||||
#define IGC_DEV_ID_I225_LMVP 0x5502
|
||||
#define IGC_DEV_ID_I226_K 0x5504
|
||||
#define IGC_DEV_ID_I225_IT 0x0D9F
|
||||
#define IGC_DEV_ID_I226_LM 0x125B
|
||||
#define IGC_DEV_ID_I226_V 0x125C
|
||||
#define IGC_DEV_ID_I226_IT 0x125D
|
||||
#define IGC_DEV_ID_I221_V 0x125E
|
||||
#define IGC_DEV_ID_I226_BLANK_NVM 0x125F
|
||||
#define IGC_DEV_ID_I225_BLANK_NVM 0x15FD
|
||||
|
||||
#define IGC_REVISION_0 0
|
||||
#define IGC_REVISION_1 1
|
||||
#define IGC_REVISION_2 2
|
||||
#define IGC_REVISION_3 3
|
||||
#define IGC_REVISION_4 4
|
||||
|
||||
#define IGC_FUNC_1 1
|
||||
|
||||
#define IGC_ALT_MAC_ADDRESS_OFFSET_LAN0 0
|
||||
#define IGC_ALT_MAC_ADDRESS_OFFSET_LAN1 3
|
||||
|
||||
enum igc_mac_type {
|
||||
igc_undefined = 0,
|
||||
igc_i225,
|
||||
igc_num_macs /* List is 1-based, so subtract 1 for TRUE count. */
|
||||
};
|
||||
|
||||
enum igc_media_type {
|
||||
igc_media_type_unknown = 0,
|
||||
igc_media_type_copper = 1,
|
||||
igc_num_media_types
|
||||
};
|
||||
|
||||
enum igc_nvm_type {
|
||||
igc_nvm_unknown = 0,
|
||||
igc_nvm_eeprom_spi,
|
||||
igc_nvm_flash_hw,
|
||||
igc_nvm_invm,
|
||||
};
|
||||
|
||||
enum igc_phy_type {
|
||||
igc_phy_unknown = 0,
|
||||
igc_phy_none,
|
||||
igc_phy_i225,
|
||||
};
|
||||
|
||||
enum igc_bus_type {
|
||||
igc_bus_type_unknown = 0,
|
||||
igc_bus_type_pci,
|
||||
igc_bus_type_pcix,
|
||||
igc_bus_type_pci_express,
|
||||
igc_bus_type_reserved
|
||||
};
|
||||
|
||||
enum igc_bus_speed {
|
||||
igc_bus_speed_unknown = 0,
|
||||
igc_bus_speed_33,
|
||||
igc_bus_speed_66,
|
||||
igc_bus_speed_100,
|
||||
igc_bus_speed_120,
|
||||
igc_bus_speed_133,
|
||||
igc_bus_speed_2500,
|
||||
igc_bus_speed_5000,
|
||||
igc_bus_speed_reserved
|
||||
};
|
||||
|
||||
enum igc_bus_width {
|
||||
igc_bus_width_unknown = 0,
|
||||
igc_bus_width_pcie_x1,
|
||||
igc_bus_width_pcie_x2,
|
||||
igc_bus_width_pcie_x4 = 4,
|
||||
igc_bus_width_pcie_x8 = 8,
|
||||
igc_bus_width_32,
|
||||
igc_bus_width_64,
|
||||
igc_bus_width_reserved
|
||||
};
|
||||
|
||||
enum igc_fc_mode {
|
||||
igc_fc_none = 0,
|
||||
igc_fc_rx_pause,
|
||||
igc_fc_tx_pause,
|
||||
igc_fc_full,
|
||||
igc_fc_default = 0xFF
|
||||
};
|
||||
|
||||
enum igc_ms_type {
|
||||
igc_ms_hw_default = 0,
|
||||
igc_ms_force_master,
|
||||
igc_ms_force_slave,
|
||||
igc_ms_auto
|
||||
};
|
||||
|
||||
enum igc_smart_speed {
|
||||
igc_smart_speed_default = 0,
|
||||
igc_smart_speed_on,
|
||||
igc_smart_speed_off
|
||||
};
|
||||
|
||||
#define __le16 u16
|
||||
#define __le32 u32
|
||||
#define __le64 u64
|
||||
/* Receive Descriptor */
|
||||
struct igc_rx_desc {
|
||||
__le64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
__le16 length; /* Length of data DMAed into data buffer */
|
||||
__le16 csum; /* Packet checksum */
|
||||
u8 status; /* Descriptor status */
|
||||
u8 errors; /* Descriptor Errors */
|
||||
__le16 special;
|
||||
};
|
||||
|
||||
/* Receive Descriptor - Extended */
|
||||
union igc_rx_desc_extended {
|
||||
struct {
|
||||
__le64 buffer_addr;
|
||||
__le64 reserved;
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
__le32 mrq; /* Multiple Rx Queues */
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length;
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define MAX_PS_BUFFERS 4
|
||||
|
||||
/* Number of packet split data buffers (not including the header buffer) */
|
||||
#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
|
||||
|
||||
/* Receive Descriptor - Packet Split */
|
||||
union igc_rx_desc_packet_split {
|
||||
struct {
|
||||
/* one buffer for protocol header(s), three data buffers */
|
||||
__le64 buffer_addr[MAX_PS_BUFFERS];
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
__le32 mrq; /* Multiple Rx Queues */
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length0; /* length of buffer 0 */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} middle;
|
||||
struct {
|
||||
__le16 header_status;
|
||||
/* length of buffers 1-3 */
|
||||
__le16 length[PS_PAGE_BUFFERS];
|
||||
} upper;
|
||||
__le64 reserved;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Transmit Descriptor */
|
||||
struct igc_tx_desc {
|
||||
__le64 buffer_addr; /* Address of the descriptor's data buffer */
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
__le16 length; /* Data buffer length */
|
||||
u8 cso; /* Checksum offset */
|
||||
u8 cmd; /* Descriptor control */
|
||||
} flags;
|
||||
} lower;
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 css; /* Checksum start */
|
||||
__le16 special;
|
||||
} fields;
|
||||
} upper;
|
||||
};
|
||||
|
||||
/* Offload Context Descriptor */
|
||||
struct igc_context_desc {
|
||||
union {
|
||||
__le32 ip_config;
|
||||
struct {
|
||||
u8 ipcss; /* IP checksum start */
|
||||
u8 ipcso; /* IP checksum offset */
|
||||
__le16 ipcse; /* IP checksum end */
|
||||
} ip_fields;
|
||||
} lower_setup;
|
||||
union {
|
||||
__le32 tcp_config;
|
||||
struct {
|
||||
u8 tucss; /* TCP checksum start */
|
||||
u8 tucso; /* TCP checksum offset */
|
||||
__le16 tucse; /* TCP checksum end */
|
||||
} tcp_fields;
|
||||
} upper_setup;
|
||||
__le32 cmd_and_length;
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 hdr_len; /* Header length */
|
||||
__le16 mss; /* Maximum segment size */
|
||||
} fields;
|
||||
} tcp_seg_setup;
|
||||
};
|
||||
|
||||
/* Offload data descriptor */
|
||||
struct igc_data_desc {
|
||||
__le64 buffer_addr; /* Address of the descriptor's buffer address */
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
__le16 length; /* Data buffer length */
|
||||
u8 typ_len_ext;
|
||||
u8 cmd;
|
||||
} flags;
|
||||
} lower;
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
u8 status; /* Descriptor status */
|
||||
u8 popts; /* Packet Options */
|
||||
__le16 special;
|
||||
} fields;
|
||||
} upper;
|
||||
};
|
||||
|
||||
/* Statistics counters collected by the MAC */
|
||||
struct igc_hw_stats {
|
||||
u64 crcerrs;
|
||||
u64 algnerrc;
|
||||
u64 symerrs;
|
||||
u64 rxerrc;
|
||||
u64 mpc;
|
||||
u64 scc;
|
||||
u64 ecol;
|
||||
u64 mcc;
|
||||
u64 latecol;
|
||||
u64 colc;
|
||||
u64 dc;
|
||||
u64 tncrs;
|
||||
u64 sec;
|
||||
u64 rlec;
|
||||
u64 xonrxc;
|
||||
u64 xontxc;
|
||||
u64 xoffrxc;
|
||||
u64 xofftxc;
|
||||
u64 fcruc;
|
||||
u64 prc64;
|
||||
u64 prc127;
|
||||
u64 prc255;
|
||||
u64 prc511;
|
||||
u64 prc1023;
|
||||
u64 prc1522;
|
||||
u64 tlpic;
|
||||
u64 rlpic;
|
||||
u64 gprc;
|
||||
u64 bprc;
|
||||
u64 mprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 rnbc;
|
||||
u64 ruc;
|
||||
u64 rfc;
|
||||
u64 roc;
|
||||
u64 rjc;
|
||||
u64 mgprc;
|
||||
u64 mgpdc;
|
||||
u64 mgptc;
|
||||
u64 tor;
|
||||
u64 tot;
|
||||
u64 tpr;
|
||||
u64 tpt;
|
||||
u64 ptc64;
|
||||
u64 ptc127;
|
||||
u64 ptc255;
|
||||
u64 ptc511;
|
||||
u64 ptc1023;
|
||||
u64 ptc1522;
|
||||
u64 mptc;
|
||||
u64 bptc;
|
||||
u64 tsctc;
|
||||
u64 iac;
|
||||
u64 rxdmtc;
|
||||
u64 htdpmc;
|
||||
u64 rpthc;
|
||||
u64 hgptc;
|
||||
u64 hgorc;
|
||||
u64 hgotc;
|
||||
u64 lenerrs;
|
||||
u64 scvpc;
|
||||
u64 hrmpc;
|
||||
u64 doosync;
|
||||
u64 o2bgptc;
|
||||
u64 o2bspc;
|
||||
u64 b2ospc;
|
||||
u64 b2ogprc;
|
||||
};
|
||||
|
||||
#include "igc_mac.h"
|
||||
#include "igc_phy.h"
|
||||
#include "igc_nvm.h"
|
||||
|
||||
/* Function pointers for the MAC. */
|
||||
struct igc_mac_operations {
|
||||
s32 (*init_params)(struct igc_hw *);
|
||||
s32 (*check_for_link)(struct igc_hw *);
|
||||
void (*clear_hw_cntrs)(struct igc_hw *);
|
||||
void (*clear_vfta)(struct igc_hw *);
|
||||
s32 (*get_bus_info)(struct igc_hw *);
|
||||
void (*set_lan_id)(struct igc_hw *);
|
||||
s32 (*get_link_up_info)(struct igc_hw *, u16 *, u16 *);
|
||||
void (*update_mc_addr_list)(struct igc_hw *, u8 *, u32);
|
||||
s32 (*reset_hw)(struct igc_hw *);
|
||||
s32 (*init_hw)(struct igc_hw *);
|
||||
s32 (*setup_link)(struct igc_hw *);
|
||||
s32 (*setup_physical_interface)(struct igc_hw *);
|
||||
void (*write_vfta)(struct igc_hw *, u32, u32);
|
||||
void (*config_collision_dist)(struct igc_hw *);
|
||||
int (*rar_set)(struct igc_hw *, u8*, u32);
|
||||
s32 (*read_mac_addr)(struct igc_hw *);
|
||||
s32 (*validate_mdi_setting)(struct igc_hw *);
|
||||
s32 (*acquire_swfw_sync)(struct igc_hw *, u16);
|
||||
void (*release_swfw_sync)(struct igc_hw *, u16);
|
||||
};
|
||||
|
||||
/* When to use various PHY register access functions:
|
||||
*
|
||||
* Func Caller
|
||||
* Function Does Does When to use
|
||||
* ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* X_reg L,P,A n/a for simple PHY reg accesses
|
||||
* X_reg_locked P,A L for multiple accesses of different regs
|
||||
* on different pages
|
||||
* X_reg_page A L,P for multiple accesses of different regs
|
||||
* on the same page
|
||||
*
|
||||
* Where X=[read|write], L=locking, P=sets page, A=register access
|
||||
*
|
||||
*/
|
||||
struct igc_phy_operations {
|
||||
s32 (*init_params)(struct igc_hw *);
|
||||
s32 (*acquire)(struct igc_hw *);
|
||||
s32 (*check_reset_block)(struct igc_hw *);
|
||||
s32 (*commit)(struct igc_hw *);
|
||||
s32 (*force_speed_duplex)(struct igc_hw *);
|
||||
s32 (*get_info)(struct igc_hw *);
|
||||
s32 (*set_page)(struct igc_hw *, u16);
|
||||
s32 (*read_reg)(struct igc_hw *, u32, u16 *);
|
||||
s32 (*read_reg_locked)(struct igc_hw *, u32, u16 *);
|
||||
s32 (*read_reg_page)(struct igc_hw *, u32, u16 *);
|
||||
void (*release)(struct igc_hw *);
|
||||
s32 (*reset)(struct igc_hw *);
|
||||
s32 (*set_d0_lplu_state)(struct igc_hw *, bool);
|
||||
s32 (*set_d3_lplu_state)(struct igc_hw *, bool);
|
||||
s32 (*write_reg)(struct igc_hw *, u32, u16);
|
||||
s32 (*write_reg_locked)(struct igc_hw *, u32, u16);
|
||||
s32 (*write_reg_page)(struct igc_hw *, u32, u16);
|
||||
void (*power_up)(struct igc_hw *);
|
||||
void (*power_down)(struct igc_hw *);
|
||||
};
|
||||
|
||||
/* Function pointers for the NVM. */
|
||||
struct igc_nvm_operations {
|
||||
s32 (*init_params)(struct igc_hw *);
|
||||
s32 (*acquire)(struct igc_hw *);
|
||||
s32 (*read)(struct igc_hw *, u16, u16, u16 *);
|
||||
void (*release)(struct igc_hw *);
|
||||
void (*reload)(struct igc_hw *);
|
||||
s32 (*update)(struct igc_hw *);
|
||||
s32 (*validate)(struct igc_hw *);
|
||||
s32 (*write)(struct igc_hw *, u16, u16, u16 *);
|
||||
};
|
||||
|
||||
struct igc_info {
|
||||
s32 (*get_invariants)(struct igc_hw *hw);
|
||||
struct igc_mac_operations *mac_ops;
|
||||
const struct igc_phy_operations *phy_ops;
|
||||
struct igc_nvm_operations *nvm_ops;
|
||||
};
|
||||
|
||||
extern const struct igc_info igc_i225_info;
|
||||
|
||||
struct igc_mac_info {
|
||||
struct igc_mac_operations ops;
|
||||
u8 addr[ETH_ADDR_LEN];
|
||||
u8 perm_addr[ETH_ADDR_LEN];
|
||||
|
||||
enum igc_mac_type type;
|
||||
|
||||
u32 mc_filter_type;
|
||||
|
||||
u16 current_ifs_val;
|
||||
u16 ifs_max_val;
|
||||
u16 ifs_min_val;
|
||||
u16 ifs_ratio;
|
||||
u16 ifs_step_size;
|
||||
u16 mta_reg_count;
|
||||
u16 uta_reg_count;
|
||||
|
||||
/* Maximum size of the MTA register table in all supported adapters */
|
||||
#define MAX_MTA_REG 128
|
||||
u32 mta_shadow[MAX_MTA_REG];
|
||||
u16 rar_entry_count;
|
||||
|
||||
u8 forced_speed_duplex;
|
||||
|
||||
bool asf_firmware_present;
|
||||
bool autoneg;
|
||||
bool get_link_status;
|
||||
u32 max_frame_size;
|
||||
};
|
||||
|
||||
struct igc_phy_info {
|
||||
struct igc_phy_operations ops;
|
||||
enum igc_phy_type type;
|
||||
|
||||
enum igc_smart_speed smart_speed;
|
||||
|
||||
u32 addr;
|
||||
u32 id;
|
||||
u32 reset_delay_us; /* in usec */
|
||||
u32 revision;
|
||||
|
||||
enum igc_media_type media_type;
|
||||
|
||||
u16 autoneg_advertised;
|
||||
u16 autoneg_mask;
|
||||
|
||||
u8 mdix;
|
||||
|
||||
bool polarity_correction;
|
||||
bool speed_downgraded;
|
||||
bool autoneg_wait_to_complete;
|
||||
};
|
||||
|
||||
struct igc_nvm_info {
|
||||
struct igc_nvm_operations ops;
|
||||
enum igc_nvm_type type;
|
||||
|
||||
u16 word_size;
|
||||
u16 delay_usec;
|
||||
u16 address_bits;
|
||||
u16 opcode_bits;
|
||||
u16 page_size;
|
||||
};
|
||||
|
||||
struct igc_bus_info {
|
||||
enum igc_bus_type type;
|
||||
enum igc_bus_speed speed;
|
||||
enum igc_bus_width width;
|
||||
|
||||
u16 func;
|
||||
u16 pci_cmd_word;
|
||||
};
|
||||
|
||||
struct igc_fc_info {
|
||||
u32 high_water; /* Flow control high-water mark */
|
||||
u32 low_water; /* Flow control low-water mark */
|
||||
u16 pause_time; /* Flow control pause timer */
|
||||
u16 refresh_time; /* Flow control refresh timer */
|
||||
bool send_xon; /* Flow control send XON */
|
||||
bool strict_ieee; /* Strict IEEE mode */
|
||||
enum igc_fc_mode current_mode; /* FC mode in effect */
|
||||
enum igc_fc_mode requested_mode; /* FC mode requested by caller */
|
||||
};
|
||||
|
||||
struct igc_dev_spec_i225 {
|
||||
bool eee_disable;
|
||||
bool clear_semaphore_once;
|
||||
u32 mtu;
|
||||
};
|
||||
|
||||
struct igc_hw {
|
||||
void *back;
|
||||
|
||||
u8 *hw_addr;
|
||||
u8 *flash_address;
|
||||
unsigned long io_base;
|
||||
|
||||
struct igc_mac_info mac;
|
||||
struct igc_fc_info fc;
|
||||
struct igc_phy_info phy;
|
||||
struct igc_nvm_info nvm;
|
||||
struct igc_bus_info bus;
|
||||
|
||||
union {
|
||||
struct igc_dev_spec_i225 _i225;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
#include "igc_i225.h"
|
||||
#include "igc_base.h"
|
||||
|
||||
/* These functions must be implemented by drivers */
|
||||
s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,112 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IGC_I225_H_
|
||||
#define _IGC_I225_H_
|
||||
|
||||
bool igc_get_flash_presence_i225(struct igc_hw *hw);
|
||||
s32 igc_update_flash_i225(struct igc_hw *hw);
|
||||
s32 igc_update_nvm_checksum_i225(struct igc_hw *hw);
|
||||
s32 igc_validate_nvm_checksum_i225(struct igc_hw *hw);
|
||||
s32 igc_write_nvm_srwr_i225(struct igc_hw *hw, u16 offset,
|
||||
u16 words, u16 *data);
|
||||
s32 igc_read_nvm_srrd_i225(struct igc_hw *hw, u16 offset,
|
||||
u16 words, u16 *data);
|
||||
s32 igc_set_flsw_flash_burst_counter_i225(struct igc_hw *hw,
|
||||
u32 burst_counter);
|
||||
s32 igc_write_erase_flash_command_i225(struct igc_hw *hw, u32 opcode,
|
||||
u32 address);
|
||||
s32 igc_check_for_link_i225(struct igc_hw *hw);
|
||||
s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask);
|
||||
void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask);
|
||||
s32 igc_init_hw_i225(struct igc_hw *hw);
|
||||
s32 igc_setup_copper_link_i225(struct igc_hw *hw);
|
||||
s32 igc_set_d0_lplu_state_i225(struct igc_hw *hw, bool active);
|
||||
s32 igc_set_d3_lplu_state_i225(struct igc_hw *hw, bool active);
|
||||
s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G,
|
||||
bool adv100M);
|
||||
|
||||
#define ID_LED_DEFAULT_I225 ((ID_LED_OFF1_ON2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_OFF2))
|
||||
#define ID_LED_DEFAULT_I225_SERDES ((ID_LED_DEF1_DEF2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_ON2))
|
||||
|
||||
/* NVM offset defaults for I225 devices */
|
||||
#define NVM_INIT_CTRL_2_DEFAULT_I225 0X7243
|
||||
#define NVM_INIT_CTRL_4_DEFAULT_I225 0x00C1
|
||||
#define NVM_LED_1_CFG_DEFAULT_I225 0x0184
|
||||
#define NVM_LED_0_2_CFG_DEFAULT_I225 0x200C
|
||||
|
||||
#define IGC_MRQC_ENABLE_RSS_4Q 0x00000002
|
||||
#define IGC_MRQC_ENABLE_VMDQ 0x00000003
|
||||
#define IGC_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
|
||||
#define IGC_I225_SHADOW_RAM_SIZE 4096
|
||||
#define IGC_I225_ERASE_CMD_OPCODE 0x02000000
|
||||
#define IGC_I225_WRITE_CMD_OPCODE 0x01000000
|
||||
#define IGC_FLSWCTL_DONE 0x40000000
|
||||
#define IGC_FLSWCTL_CMDV 0x10000000
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define IGC_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
|
||||
#define IGC_SRRCTL_DESCTYPE_LEGACY 0x00000000
|
||||
#define IGC_SRRCTL_DESCTYPE_HDR_SPLIT 0x04000000
|
||||
#define IGC_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
#define IGC_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
|
||||
#define IGC_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
|
||||
#define IGC_SRRCTL_DESCTYPE_MASK 0x0E000000
|
||||
#define IGC_SRRCTL_DROP_EN 0x80000000
|
||||
#define IGC_SRRCTL_BSIZEPKT_MASK 0x0000007F
|
||||
#define IGC_SRRCTL_BSIZEHDR_MASK 0x00003F00
|
||||
|
||||
#define IGC_RXDADV_RSSTYPE_MASK 0x0000000F
|
||||
#define IGC_RXDADV_RSSTYPE_SHIFT 12
|
||||
#define IGC_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define IGC_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
#define IGC_RXDADV_SPLITHEADER_EN 0x00001000
|
||||
#define IGC_RXDADV_SPH 0x8000
|
||||
#define IGC_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */
|
||||
#define IGC_RXDADV_ERR_HBO 0x00800000
|
||||
|
||||
/* RSS Hash results */
|
||||
#define IGC_RXDADV_RSSTYPE_NONE 0x00000000
|
||||
#define IGC_RXDADV_RSSTYPE_IPV4_TCP 0x00000001
|
||||
#define IGC_RXDADV_RSSTYPE_IPV4 0x00000002
|
||||
#define IGC_RXDADV_RSSTYPE_IPV6_TCP 0x00000003
|
||||
#define IGC_RXDADV_RSSTYPE_IPV6_EX 0x00000004
|
||||
#define IGC_RXDADV_RSSTYPE_IPV6 0x00000005
|
||||
#define IGC_RXDADV_RSSTYPE_IPV6_TCP_EX 0x00000006
|
||||
#define IGC_RXDADV_RSSTYPE_IPV4_UDP 0x00000007
|
||||
#define IGC_RXDADV_RSSTYPE_IPV6_UDP 0x00000008
|
||||
#define IGC_RXDADV_RSSTYPE_IPV6_UDP_EX 0x00000009
|
||||
|
||||
/* RSS Packet Types as indicated in the receive descriptor */
|
||||
#define IGC_RXDADV_PKTTYPE_ILMASK 0x000000F0
|
||||
#define IGC_RXDADV_PKTTYPE_TLMASK 0x00000F00
|
||||
#define IGC_RXDADV_PKTTYPE_NONE 0x00000000
|
||||
#define IGC_RXDADV_PKTTYPE_IPV4 0x00000010 /* IPV4 hdr present */
|
||||
#define IGC_RXDADV_PKTTYPE_IPV4_EX 0x00000020 /* IPV4 hdr + extensions */
|
||||
#define IGC_RXDADV_PKTTYPE_IPV6 0x00000040 /* IPV6 hdr present */
|
||||
#define IGC_RXDADV_PKTTYPE_IPV6_EX 0x00000080 /* IPV6 hdr + extensions */
|
||||
#define IGC_RXDADV_PKTTYPE_TCP 0x00000100 /* TCP hdr present */
|
||||
#define IGC_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */
|
||||
#define IGC_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */
|
||||
#define IGC_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */
|
||||
|
||||
#define IGC_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */
|
||||
#define IGC_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */
|
||||
#define IGC_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */
|
||||
#define IGC_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */
|
||||
#define IGC_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */
|
||||
#define IGC_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IGC_MAC_H_
|
||||
#define _IGC_MAC_H_
|
||||
|
||||
void igc_init_mac_ops_generic(struct igc_hw *hw);
|
||||
void igc_null_mac_generic(struct igc_hw *hw);
|
||||
s32 igc_null_ops_generic(struct igc_hw *hw);
|
||||
s32 igc_null_link_info(struct igc_hw *hw, u16 *s, u16 *d);
|
||||
bool igc_null_mng_mode(struct igc_hw *hw);
|
||||
void igc_null_update_mc(struct igc_hw *hw, u8 *h, u32 a);
|
||||
void igc_null_write_vfta(struct igc_hw *hw, u32 a, u32 b);
|
||||
int igc_null_rar_set(struct igc_hw *hw, u8 *h, u32 a);
|
||||
s32 igc_check_for_copper_link_generic(struct igc_hw *hw);
|
||||
s32 igc_config_fc_after_link_up_generic(struct igc_hw *hw);
|
||||
s32 igc_disable_pcie_master_generic(struct igc_hw *hw);
|
||||
s32 igc_force_mac_fc_generic(struct igc_hw *hw);
|
||||
s32 igc_get_auto_rd_done_generic(struct igc_hw *hw);
|
||||
s32 igc_get_bus_info_pcie_generic(struct igc_hw *hw);
|
||||
void igc_set_lan_id_single_port(struct igc_hw *hw);
|
||||
s32 igc_get_hw_semaphore_generic(struct igc_hw *hw);
|
||||
s32 igc_get_speed_and_duplex_copper_generic(struct igc_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
void igc_update_mc_addr_list_generic(struct igc_hw *hw,
|
||||
u8 *mc_addr_list, u32 mc_addr_count);
|
||||
int igc_rar_set_generic(struct igc_hw *hw, u8 *addr, u32 index);
|
||||
s32 igc_set_fc_watermarks_generic(struct igc_hw *hw);
|
||||
s32 igc_setup_link_generic(struct igc_hw *hw);
|
||||
s32 igc_validate_mdi_setting_crossover_generic(struct igc_hw *hw);
|
||||
|
||||
u32 igc_hash_mc_addr_generic(struct igc_hw *hw, u8 *mc_addr);
|
||||
|
||||
void igc_clear_hw_cntrs_base_generic(struct igc_hw *hw);
|
||||
void igc_clear_vfta_generic(struct igc_hw *hw);
|
||||
void igc_init_rx_addrs_generic(struct igc_hw *hw, u16 rar_count);
|
||||
void igc_pcix_mmrbc_workaround_generic(struct igc_hw *hw);
|
||||
void igc_put_hw_semaphore_generic(struct igc_hw *hw);
|
||||
s32 igc_check_alt_mac_addr_generic(struct igc_hw *hw);
|
||||
void igc_set_pcie_no_snoop_generic(struct igc_hw *hw, u32 no_snoop);
|
||||
void igc_write_vfta_generic(struct igc_hw *hw, u32 offset, u32 value);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,721 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "igc_api.h"
|
||||
|
||||
static void igc_reload_nvm_generic(struct igc_hw *hw);
|
||||
|
||||
/**
|
||||
* igc_init_nvm_ops_generic - Initialize NVM function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setups up the function pointers to no-op functions
|
||||
**/
|
||||
void igc_init_nvm_ops_generic(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
DEBUGFUNC("igc_init_nvm_ops_generic");
|
||||
|
||||
/* Initialize function pointers */
|
||||
nvm->ops.init_params = igc_null_ops_generic;
|
||||
nvm->ops.acquire = igc_null_ops_generic;
|
||||
nvm->ops.read = igc_null_read_nvm;
|
||||
nvm->ops.release = igc_null_nvm_generic;
|
||||
nvm->ops.reload = igc_reload_nvm_generic;
|
||||
nvm->ops.update = igc_null_ops_generic;
|
||||
nvm->ops.validate = igc_null_ops_generic;
|
||||
nvm->ops.write = igc_null_write_nvm;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_null_nvm_read - No-op function, return 0
|
||||
* @hw: pointer to the HW structure
|
||||
* @a: dummy variable
|
||||
* @b: dummy variable
|
||||
* @c: dummy variable
|
||||
**/
|
||||
s32 igc_null_read_nvm(struct igc_hw IGC_UNUSEDARG *hw,
|
||||
u16 IGC_UNUSEDARG a, u16 IGC_UNUSEDARG b,
|
||||
u16 IGC_UNUSEDARG *c)
|
||||
{
|
||||
DEBUGFUNC("igc_null_read_nvm");
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_null_nvm_generic - No-op function, return void
|
||||
* @hw: pointer to the HW structure
|
||||
**/
|
||||
void igc_null_nvm_generic(struct igc_hw IGC_UNUSEDARG *hw)
|
||||
{
|
||||
DEBUGFUNC("igc_null_nvm_generic");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_null_write_nvm - No-op function, return 0
|
||||
* @hw: pointer to the HW structure
|
||||
* @a: dummy variable
|
||||
* @b: dummy variable
|
||||
* @c: dummy variable
|
||||
**/
|
||||
s32 igc_null_write_nvm(struct igc_hw IGC_UNUSEDARG *hw,
|
||||
u16 IGC_UNUSEDARG a, u16 IGC_UNUSEDARG b,
|
||||
u16 IGC_UNUSEDARG *c)
|
||||
{
|
||||
DEBUGFUNC("igc_null_write_nvm");
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_raise_eec_clk - Raise EEPROM clock
|
||||
* @hw: pointer to the HW structure
|
||||
* @eecd: pointer to the EEPROM
|
||||
*
|
||||
* Enable/Raise the EEPROM clock bit.
|
||||
**/
|
||||
static void igc_raise_eec_clk(struct igc_hw *hw, u32 *eecd)
|
||||
{
|
||||
*eecd = *eecd | IGC_EECD_SK;
|
||||
IGC_WRITE_REG(hw, IGC_EECD, *eecd);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
usec_delay(hw->nvm.delay_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_lower_eec_clk - Lower EEPROM clock
|
||||
* @hw: pointer to the HW structure
|
||||
* @eecd: pointer to the EEPROM
|
||||
*
|
||||
* Clear/Lower the EEPROM clock bit.
|
||||
**/
|
||||
static void igc_lower_eec_clk(struct igc_hw *hw, u32 *eecd)
|
||||
{
|
||||
*eecd = *eecd & ~IGC_EECD_SK;
|
||||
IGC_WRITE_REG(hw, IGC_EECD, *eecd);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
usec_delay(hw->nvm.delay_usec);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_shift_out_eec_bits - Shift data bits our to the EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
* @data: data to send to the EEPROM
|
||||
* @count: number of bits to shift out
|
||||
*
|
||||
* We need to shift 'count' bits out to the EEPROM. So, the value in the
|
||||
* "data" parameter will be shifted out to the EEPROM one bit at a time.
|
||||
* In order to do this, "data" must be broken down into bits.
|
||||
**/
|
||||
static void igc_shift_out_eec_bits(struct igc_hw *hw, u16 data, u16 count)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
u32 mask;
|
||||
|
||||
DEBUGFUNC("igc_shift_out_eec_bits");
|
||||
|
||||
mask = 0x01 << (count - 1);
|
||||
if (nvm->type == igc_nvm_eeprom_spi)
|
||||
eecd |= IGC_EECD_DO;
|
||||
|
||||
do {
|
||||
eecd &= ~IGC_EECD_DI;
|
||||
|
||||
if (data & mask)
|
||||
eecd |= IGC_EECD_DI;
|
||||
|
||||
IGC_WRITE_REG(hw, IGC_EECD, eecd);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
|
||||
usec_delay(nvm->delay_usec);
|
||||
|
||||
igc_raise_eec_clk(hw, &eecd);
|
||||
igc_lower_eec_clk(hw, &eecd);
|
||||
|
||||
mask >>= 1;
|
||||
} while (mask);
|
||||
|
||||
eecd &= ~IGC_EECD_DI;
|
||||
IGC_WRITE_REG(hw, IGC_EECD, eecd);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_shift_in_eec_bits - Shift data bits in from the EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
* @count: number of bits to shift in
|
||||
*
|
||||
* In order to read a register from the EEPROM, we need to shift 'count' bits
|
||||
* in from the EEPROM. Bits are "shifted in" by raising the clock input to
|
||||
* the EEPROM (setting the SK bit), and then reading the value of the data out
|
||||
* "DO" bit. During this "shifting in" process the data in "DI" bit should
|
||||
* always be clear.
|
||||
**/
|
||||
static u16 igc_shift_in_eec_bits(struct igc_hw *hw, u16 count)
|
||||
{
|
||||
u32 eecd;
|
||||
u32 i;
|
||||
u16 data;
|
||||
|
||||
DEBUGFUNC("igc_shift_in_eec_bits");
|
||||
|
||||
eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
|
||||
eecd &= ~(IGC_EECD_DO | IGC_EECD_DI);
|
||||
data = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
data <<= 1;
|
||||
igc_raise_eec_clk(hw, &eecd);
|
||||
|
||||
eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
|
||||
eecd &= ~IGC_EECD_DI;
|
||||
if (eecd & IGC_EECD_DO)
|
||||
data |= 1;
|
||||
|
||||
igc_lower_eec_clk(hw, &eecd);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion
|
||||
* @hw: pointer to the HW structure
|
||||
* @ee_reg: EEPROM flag for polling
|
||||
*
|
||||
* Polls the EEPROM status bit for either read or write completion based
|
||||
* upon the value of 'ee_reg'.
|
||||
**/
|
||||
s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
|
||||
{
|
||||
u32 attempts = 100000;
|
||||
u32 i, reg = 0;
|
||||
|
||||
DEBUGFUNC("igc_poll_eerd_eewr_done");
|
||||
|
||||
for (i = 0; i < attempts; i++) {
|
||||
if (ee_reg == IGC_NVM_POLL_READ)
|
||||
reg = IGC_READ_REG(hw, IGC_EERD);
|
||||
else
|
||||
reg = IGC_READ_REG(hw, IGC_EEWR);
|
||||
|
||||
if (reg & IGC_NVM_RW_REG_DONE)
|
||||
return IGC_SUCCESS;
|
||||
|
||||
usec_delay(5);
|
||||
}
|
||||
|
||||
return -IGC_ERR_NVM;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_acquire_nvm_generic - Generic request for access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
|
||||
* Return successful if access grant bit set, else clear the request for
|
||||
* EEPROM access and return -IGC_ERR_NVM (-1).
|
||||
**/
|
||||
s32 igc_acquire_nvm_generic(struct igc_hw *hw)
|
||||
{
|
||||
u32 eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
|
||||
|
||||
DEBUGFUNC("igc_acquire_nvm_generic");
|
||||
|
||||
IGC_WRITE_REG(hw, IGC_EECD, eecd | IGC_EECD_REQ);
|
||||
eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
|
||||
while (timeout) {
|
||||
if (eecd & IGC_EECD_GNT)
|
||||
break;
|
||||
usec_delay(5);
|
||||
eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
eecd &= ~IGC_EECD_REQ;
|
||||
IGC_WRITE_REG(hw, IGC_EECD, eecd);
|
||||
DEBUGOUT("Could not acquire NVM grant\n");
|
||||
return -IGC_ERR_NVM;
|
||||
}
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_standby_nvm - Return EEPROM to standby state
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Return the EEPROM to a standby state.
|
||||
**/
|
||||
static void igc_standby_nvm(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
|
||||
DEBUGFUNC("igc_standby_nvm");
|
||||
|
||||
if (nvm->type == igc_nvm_eeprom_spi) {
|
||||
/* Toggle CS to flush commands */
|
||||
eecd |= IGC_EECD_CS;
|
||||
IGC_WRITE_REG(hw, IGC_EECD, eecd);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
usec_delay(nvm->delay_usec);
|
||||
eecd &= ~IGC_EECD_CS;
|
||||
IGC_WRITE_REG(hw, IGC_EECD, eecd);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
usec_delay(nvm->delay_usec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_stop_nvm - Terminate EEPROM command
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Terminates the current command by inverting the EEPROM's chip select pin.
|
||||
**/
|
||||
static void igc_stop_nvm(struct igc_hw *hw)
|
||||
{
|
||||
u32 eecd;
|
||||
|
||||
DEBUGFUNC("igc_stop_nvm");
|
||||
|
||||
eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
if (hw->nvm.type == igc_nvm_eeprom_spi) {
|
||||
/* Pull CS high */
|
||||
eecd |= IGC_EECD_CS;
|
||||
igc_lower_eec_clk(hw, &eecd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_release_nvm_generic - Release exclusive access to EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Stop any current commands to the EEPROM and clear the EEPROM request bit.
|
||||
**/
|
||||
void igc_release_nvm_generic(struct igc_hw *hw)
|
||||
{
|
||||
u32 eecd;
|
||||
|
||||
DEBUGFUNC("igc_release_nvm_generic");
|
||||
|
||||
igc_stop_nvm(hw);
|
||||
|
||||
eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
eecd &= ~IGC_EECD_REQ;
|
||||
IGC_WRITE_REG(hw, IGC_EECD, eecd);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_ready_nvm_eeprom - Prepares EEPROM for read/write
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setups the EEPROM for reading and writing.
|
||||
**/
|
||||
static s32 igc_ready_nvm_eeprom(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = IGC_READ_REG(hw, IGC_EECD);
|
||||
u8 spi_stat_reg;
|
||||
|
||||
DEBUGFUNC("igc_ready_nvm_eeprom");
|
||||
|
||||
if (nvm->type == igc_nvm_eeprom_spi) {
|
||||
u16 timeout = NVM_MAX_RETRY_SPI;
|
||||
|
||||
/* Clear SK and CS */
|
||||
eecd &= ~(IGC_EECD_CS | IGC_EECD_SK);
|
||||
IGC_WRITE_REG(hw, IGC_EECD, eecd);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
usec_delay(1);
|
||||
|
||||
/* Read "Status Register" repeatedly until the LSB is cleared.
|
||||
* The EEPROM will signal that the command has been completed
|
||||
* by clearing bit 0 of the internal status register. If it's
|
||||
* not cleared within 'timeout', then error out.
|
||||
*/
|
||||
while (timeout) {
|
||||
igc_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
|
||||
hw->nvm.opcode_bits);
|
||||
spi_stat_reg = (u8)igc_shift_in_eec_bits(hw, 8);
|
||||
if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
|
||||
break;
|
||||
|
||||
usec_delay(5);
|
||||
igc_standby_nvm(hw);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
DEBUGOUT("SPI NVM Status error\n");
|
||||
return -IGC_ERR_NVM;
|
||||
}
|
||||
}
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_read_nvm_eerd - Reads EEPROM using EERD register
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of word in the EEPROM to read
|
||||
* @words: number of words to read
|
||||
* @data: word read from the EEPROM
|
||||
*
|
||||
* Reads a 16 bit word from the EEPROM using the EERD register.
|
||||
**/
|
||||
s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
u32 i, eerd = 0;
|
||||
s32 ret_val = IGC_SUCCESS;
|
||||
|
||||
DEBUGFUNC("igc_read_nvm_eerd");
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* too many words for the offset, and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
DEBUGOUT("nvm parameter(s) out of bounds\n");
|
||||
return -IGC_ERR_NVM;
|
||||
}
|
||||
|
||||
for (i = 0; i < words; i++) {
|
||||
eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) +
|
||||
IGC_NVM_RW_REG_START;
|
||||
|
||||
IGC_WRITE_REG(hw, IGC_EERD, eerd);
|
||||
ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ);
|
||||
if (ret_val)
|
||||
break;
|
||||
|
||||
data[i] = (IGC_READ_REG(hw, IGC_EERD) >>
|
||||
IGC_NVM_RW_REG_DATA);
|
||||
}
|
||||
|
||||
if (ret_val)
|
||||
DEBUGOUT1("NVM read error: %d\n", ret_val);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_write_nvm_spi - Write to EEPROM using SPI
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset within the EEPROM to be written to
|
||||
* @words: number of words to write
|
||||
* @data: 16 bit word(s) to be written to the EEPROM
|
||||
*
|
||||
* Writes data to EEPROM at offset using SPI interface.
|
||||
*
|
||||
* If igc_update_nvm_checksum is not called after this function , the
|
||||
* EEPROM will most likely contain an invalid checksum.
|
||||
**/
|
||||
s32 igc_write_nvm_spi(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
s32 ret_val = -IGC_ERR_NVM;
|
||||
u16 widx = 0;
|
||||
|
||||
DEBUGFUNC("igc_write_nvm_spi");
|
||||
|
||||
/* A check for invalid values: offset too large, too many words,
|
||||
* and not enough words.
|
||||
*/
|
||||
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
|
||||
(words == 0)) {
|
||||
DEBUGOUT("nvm parameter(s) out of bounds\n");
|
||||
return -IGC_ERR_NVM;
|
||||
}
|
||||
|
||||
while (widx < words) {
|
||||
u8 write_opcode = NVM_WRITE_OPCODE_SPI;
|
||||
|
||||
ret_val = nvm->ops.acquire(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
ret_val = igc_ready_nvm_eeprom(hw);
|
||||
if (ret_val) {
|
||||
nvm->ops.release(hw);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
igc_standby_nvm(hw);
|
||||
|
||||
/* Send the WRITE ENABLE command (8 bit opcode) */
|
||||
igc_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
|
||||
nvm->opcode_bits);
|
||||
|
||||
igc_standby_nvm(hw);
|
||||
|
||||
/* Some SPI eeproms use the 8th address bit embedded in the
|
||||
* opcode
|
||||
*/
|
||||
if ((nvm->address_bits == 8) && (offset >= 128))
|
||||
write_opcode |= NVM_A8_OPCODE_SPI;
|
||||
|
||||
/* Send the Write command (8-bit opcode + addr) */
|
||||
igc_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
|
||||
igc_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
|
||||
nvm->address_bits);
|
||||
|
||||
/* Loop to allow for up to whole page write of eeprom */
|
||||
while (widx < words) {
|
||||
u16 word_out = data[widx];
|
||||
word_out = (word_out >> 8) | (word_out << 8);
|
||||
igc_shift_out_eec_bits(hw, word_out, 16);
|
||||
widx++;
|
||||
|
||||
if ((((offset + widx) * 2) % nvm->page_size) == 0) {
|
||||
igc_standby_nvm(hw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
msec_delay(10);
|
||||
nvm->ops.release(hw);
|
||||
}
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_read_pba_string_generic - Read device part number
|
||||
* @hw: pointer to the HW structure
|
||||
* @pba_num: pointer to device part number
|
||||
* @pba_num_size: size of part number buffer
|
||||
*
|
||||
* Reads the product board assembly (PBA) number from the EEPROM and stores
|
||||
* the value in pba_num.
|
||||
**/
|
||||
s32 igc_read_pba_string_generic(struct igc_hw *hw, u8 *pba_num,
|
||||
u32 pba_num_size)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 nvm_data;
|
||||
u16 pba_ptr;
|
||||
u16 offset;
|
||||
u16 length;
|
||||
|
||||
DEBUGFUNC("igc_read_pba_string_generic");
|
||||
|
||||
if (pba_num == NULL) {
|
||||
DEBUGOUT("PBA string buffer was null\n");
|
||||
return -IGC_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* if nvm_data is not ptr guard the PBA must be in legacy format which
|
||||
* means pba_ptr is actually our second data word for the PBA number
|
||||
* and we can decode it into an ascii string
|
||||
*/
|
||||
if (nvm_data != NVM_PBA_PTR_GUARD) {
|
||||
DEBUGOUT("NVM PBA number is not stored as string\n");
|
||||
|
||||
/* make sure callers buffer is big enough to store the PBA */
|
||||
if (pba_num_size < IGC_PBANUM_LENGTH) {
|
||||
DEBUGOUT("PBA string buffer too small\n");
|
||||
return IGC_ERR_NO_SPACE;
|
||||
}
|
||||
|
||||
/* extract hex string from data and pba_ptr */
|
||||
pba_num[0] = (nvm_data >> 12) & 0xF;
|
||||
pba_num[1] = (nvm_data >> 8) & 0xF;
|
||||
pba_num[2] = (nvm_data >> 4) & 0xF;
|
||||
pba_num[3] = nvm_data & 0xF;
|
||||
pba_num[4] = (pba_ptr >> 12) & 0xF;
|
||||
pba_num[5] = (pba_ptr >> 8) & 0xF;
|
||||
pba_num[6] = '-';
|
||||
pba_num[7] = 0;
|
||||
pba_num[8] = (pba_ptr >> 4) & 0xF;
|
||||
pba_num[9] = pba_ptr & 0xF;
|
||||
|
||||
/* put a null character on the end of our string */
|
||||
pba_num[10] = '\0';
|
||||
|
||||
/* switch all the data but the '-' to hex char */
|
||||
for (offset = 0; offset < 10; offset++) {
|
||||
if (pba_num[offset] < 0xA)
|
||||
pba_num[offset] += '0';
|
||||
else if (pba_num[offset] < 0x10)
|
||||
pba_num[offset] += 'A' - 0xA;
|
||||
}
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
if (length == 0xFFFF || length == 0) {
|
||||
DEBUGOUT("NVM PBA number section invalid length\n");
|
||||
return -IGC_ERR_NVM_PBA_SECTION;
|
||||
}
|
||||
/* check if pba_num buffer is big enough */
|
||||
if (pba_num_size < (((u32)length * 2) - 1)) {
|
||||
DEBUGOUT("PBA string buffer too small\n");
|
||||
return -IGC_ERR_NO_SPACE;
|
||||
}
|
||||
|
||||
/* trim pba length from start of string */
|
||||
pba_ptr++;
|
||||
length--;
|
||||
|
||||
for (offset = 0; offset < length; offset++) {
|
||||
ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
return ret_val;
|
||||
}
|
||||
pba_num[offset * 2] = (u8)(nvm_data >> 8);
|
||||
pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
|
||||
}
|
||||
pba_num[offset * 2] = '\0';
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* igc_read_mac_addr_generic - Read device MAC address
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reads the device MAC address from the EEPROM and stores the value.
|
||||
* Since devices with two ports use the same EEPROM, we increment the
|
||||
* last bit in the MAC address for the second port.
|
||||
**/
|
||||
s32 igc_read_mac_addr_generic(struct igc_hw *hw)
|
||||
{
|
||||
u32 rar_high;
|
||||
u32 rar_low;
|
||||
u16 i;
|
||||
|
||||
rar_high = IGC_READ_REG(hw, IGC_RAH(0));
|
||||
rar_low = IGC_READ_REG(hw, IGC_RAL(0));
|
||||
|
||||
for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++)
|
||||
hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
|
||||
|
||||
for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++)
|
||||
hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
|
||||
|
||||
for (i = 0; i < ETH_ADDR_LEN; i++)
|
||||
hw->mac.addr[i] = hw->mac.perm_addr[i];
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_validate_nvm_checksum_generic - Validate EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
|
||||
**/
|
||||
s32 igc_validate_nvm_checksum_generic(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
DEBUGFUNC("igc_validate_nvm_checksum_generic");
|
||||
|
||||
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
|
||||
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error\n");
|
||||
return ret_val;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
|
||||
if (checksum != (u16) NVM_SUM) {
|
||||
DEBUGOUT("NVM Checksum Invalid\n");
|
||||
return -IGC_ERR_NVM;
|
||||
}
|
||||
|
||||
return IGC_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_update_nvm_checksum_generic - Update EEPROM checksum
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
|
||||
* up to the checksum. Then calculates the EEPROM checksum and writes the
|
||||
* value to the EEPROM.
|
||||
**/
|
||||
s32 igc_update_nvm_checksum_generic(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u16 checksum = 0;
|
||||
u16 i, nvm_data;
|
||||
|
||||
DEBUGFUNC("igc_update_nvm_checksum");
|
||||
|
||||
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
|
||||
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
|
||||
if (ret_val) {
|
||||
DEBUGOUT("NVM Read Error while updating checksum.\n");
|
||||
return ret_val;
|
||||
}
|
||||
checksum += nvm_data;
|
||||
}
|
||||
checksum = (u16) NVM_SUM - checksum;
|
||||
ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
|
||||
if (ret_val)
|
||||
DEBUGOUT("NVM Write Error while updating checksum.\n");
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_reload_nvm_generic - Reloads EEPROM
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
|
||||
* extended control register.
|
||||
**/
|
||||
static void igc_reload_nvm_generic(struct igc_hw *hw)
|
||||
{
|
||||
u32 ctrl_ext;
|
||||
|
||||
DEBUGFUNC("igc_reload_nvm_generic");
|
||||
|
||||
usec_delay(10);
|
||||
ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
|
||||
ctrl_ext |= IGC_CTRL_EXT_EE_RST;
|
||||
IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
|
||||
IGC_WRITE_FLUSH(hw);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IGC_NVM_H_
|
||||
#define _IGC_NVM_H_
|
||||
|
||||
void igc_init_nvm_ops_generic(struct igc_hw *hw);
|
||||
s32 igc_null_read_nvm(struct igc_hw *hw, u16 a, u16 b, u16 *c);
|
||||
void igc_null_nvm_generic(struct igc_hw *hw);
|
||||
s32 igc_null_led_default(struct igc_hw *hw, u16 *data);
|
||||
s32 igc_null_write_nvm(struct igc_hw *hw, u16 a, u16 b, u16 *c);
|
||||
s32 igc_acquire_nvm_generic(struct igc_hw *hw);
|
||||
|
||||
s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg);
|
||||
s32 igc_read_mac_addr_generic(struct igc_hw *hw);
|
||||
s32 igc_read_pba_string_generic(struct igc_hw *hw, u8 *pba_num,
|
||||
u32 pba_num_size);
|
||||
s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words,
|
||||
u16 *data);
|
||||
s32 igc_valid_led_default_generic(struct igc_hw *hw, u16 *data);
|
||||
s32 igc_validate_nvm_checksum_generic(struct igc_hw *hw);
|
||||
s32 igc_write_nvm_spi(struct igc_hw *hw, u16 offset, u16 words,
|
||||
u16 *data);
|
||||
s32 igc_update_nvm_checksum_generic(struct igc_hw *hw);
|
||||
void igc_release_nvm_generic(struct igc_hw *hw);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,133 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _FREEBSD_OS_H_
|
||||
#define _FREEBSD_OS_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_var.h>
|
||||
#include <net/iflib.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
#include <machine/resource.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <machine/clock.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
|
||||
#define usec_delay(x) DELAY(x)
|
||||
#define usec_delay_irq(x) usec_delay(x)
|
||||
#define msec_delay(x) DELAY(1000*(x))
|
||||
#define msec_delay_irq(x) DELAY(1000*(x))
|
||||
|
||||
/* Enable/disable debugging statements in shared code */
|
||||
#define DBG 0
|
||||
|
||||
#define DEBUGOUT(...) \
|
||||
do { if (DBG) printf(__VA_ARGS__); } while (0)
|
||||
#define DEBUGOUT1(...) DEBUGOUT(__VA_ARGS__)
|
||||
#define DEBUGOUT2(...) DEBUGOUT(__VA_ARGS__)
|
||||
#define DEBUGOUT3(...) DEBUGOUT(__VA_ARGS__)
|
||||
#define DEBUGOUT7(...) DEBUGOUT(__VA_ARGS__)
|
||||
#define DEBUGFUNC(F) DEBUGOUT(F "\n")
|
||||
|
||||
typedef uint64_t u64;
|
||||
typedef uint32_t u32;
|
||||
typedef uint16_t u16;
|
||||
typedef uint8_t u8;
|
||||
typedef int64_t s64;
|
||||
typedef int32_t s32;
|
||||
typedef int16_t s16;
|
||||
typedef int8_t s8;
|
||||
|
||||
#define __le16 u16
|
||||
#define __le32 u32
|
||||
#define __le64 u64
|
||||
|
||||
struct igc_osdep
|
||||
{
|
||||
bus_space_tag_t mem_bus_space_tag;
|
||||
bus_space_handle_t mem_bus_space_handle;
|
||||
bus_space_tag_t io_bus_space_tag;
|
||||
bus_space_handle_t io_bus_space_handle;
|
||||
bus_space_tag_t flash_bus_space_tag;
|
||||
bus_space_handle_t flash_bus_space_handle;
|
||||
device_t dev;
|
||||
if_ctx_t ctx;
|
||||
};
|
||||
|
||||
#define IGC_REGISTER(hw, reg) reg
|
||||
|
||||
#define IGC_WRITE_FLUSH(a) IGC_READ_REG(a, IGC_STATUS)
|
||||
|
||||
/* Read from an absolute offset in the adapter's memory space */
|
||||
#define IGC_READ_OFFSET(hw, offset) \
|
||||
bus_space_read_4(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, offset)
|
||||
|
||||
/* Write to an absolute offset in the adapter's memory space */
|
||||
#define IGC_WRITE_OFFSET(hw, offset, value) \
|
||||
bus_space_write_4(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, offset, value)
|
||||
|
||||
/* Register READ/WRITE macros */
|
||||
|
||||
#define IGC_READ_REG(hw, reg) \
|
||||
bus_space_read_4(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, \
|
||||
IGC_REGISTER(hw, reg))
|
||||
|
||||
#define IGC_WRITE_REG(hw, reg, value) \
|
||||
bus_space_write_4(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, \
|
||||
IGC_REGISTER(hw, reg), value)
|
||||
|
||||
#define IGC_READ_REG_ARRAY(hw, reg, index) \
|
||||
bus_space_read_4(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, \
|
||||
IGC_REGISTER(hw, reg) + ((index)<< 2))
|
||||
|
||||
#define IGC_WRITE_REG_ARRAY(hw, reg, index, value) \
|
||||
bus_space_write_4(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, \
|
||||
IGC_REGISTER(hw, reg) + ((index)<< 2), value)
|
||||
|
||||
#define IGC_READ_REG_ARRAY_DWORD IGC_READ_REG_ARRAY
|
||||
#define IGC_WRITE_REG_ARRAY_DWORD IGC_WRITE_REG_ARRAY
|
||||
|
||||
#define IGC_READ_REG_ARRAY_BYTE(hw, reg, index) \
|
||||
bus_space_read_1(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, \
|
||||
IGC_REGISTER(hw, reg) + index)
|
||||
|
||||
#define IGC_WRITE_REG_ARRAY_BYTE(hw, reg, index, value) \
|
||||
bus_space_write_1(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, \
|
||||
IGC_REGISTER(hw, reg) + index, value)
|
||||
|
||||
#define IGC_WRITE_REG_ARRAY_WORD(hw, reg, index, value) \
|
||||
bus_space_write_2(((struct igc_osdep *)(hw)->back)->mem_bus_space_tag, \
|
||||
((struct igc_osdep *)(hw)->back)->mem_bus_space_handle, \
|
||||
IGC_REGISTER(hw, reg) + (index << 1), value)
|
||||
|
||||
#endif /* _FREEBSD_OS_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,134 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IGC_PHY_H_
|
||||
#define _IGC_PHY_H_
|
||||
|
||||
void igc_init_phy_ops_generic(struct igc_hw *hw);
|
||||
s32 igc_null_read_reg(struct igc_hw *hw, u32 offset, u16 *data);
|
||||
void igc_null_phy_generic(struct igc_hw *hw);
|
||||
s32 igc_null_lplu_state(struct igc_hw *hw, bool active);
|
||||
s32 igc_null_write_reg(struct igc_hw *hw, u32 offset, u16 data);
|
||||
s32 igc_null_set_page(struct igc_hw *hw, u16 data);
|
||||
s32 igc_check_downshift_generic(struct igc_hw *hw);
|
||||
s32 igc_check_reset_block_generic(struct igc_hw *hw);
|
||||
s32 igc_get_phy_id(struct igc_hw *hw);
|
||||
s32 igc_phy_sw_reset_generic(struct igc_hw *hw);
|
||||
void igc_phy_force_speed_duplex_setup(struct igc_hw *hw, u16 *phy_ctrl);
|
||||
s32 igc_phy_hw_reset_generic(struct igc_hw *hw);
|
||||
s32 igc_phy_reset_dsp_generic(struct igc_hw *hw);
|
||||
s32 igc_set_d3_lplu_state_generic(struct igc_hw *hw, bool active);
|
||||
s32 igc_setup_copper_link_generic(struct igc_hw *hw);
|
||||
s32 igc_phy_has_link_generic(struct igc_hw *hw, u32 iterations,
|
||||
u32 usec_interval, bool *success);
|
||||
enum igc_phy_type igc_get_phy_type_from_id(u32 phy_id);
|
||||
s32 igc_determine_phy_address(struct igc_hw *hw);
|
||||
s32 igc_enable_phy_wakeup_reg_access_bm(struct igc_hw *hw, u16 *phy_reg);
|
||||
s32 igc_disable_phy_wakeup_reg_access_bm(struct igc_hw *hw, u16 *phy_reg);
|
||||
void igc_power_up_phy_copper(struct igc_hw *hw);
|
||||
void igc_power_down_phy_copper(struct igc_hw *hw);
|
||||
s32 igc_read_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 *data);
|
||||
s32 igc_write_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 data);
|
||||
|
||||
s32 igc_read_xmdio_reg(struct igc_hw *hw, u16 addr, u8 dev_addr,
|
||||
u16 *data);
|
||||
s32 igc_write_xmdio_reg(struct igc_hw *hw, u16 addr, u8 dev_addr,
|
||||
u16 data);
|
||||
s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data);
|
||||
s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data);
|
||||
|
||||
#define IGC_MAX_PHY_ADDR 8
|
||||
|
||||
/* IGP01IGC Specific Registers */
|
||||
#define IGP01IGC_PHY_PORT_CONFIG 0x10 /* Port Config */
|
||||
#define IGP01IGC_PHY_PORT_STATUS 0x11 /* Status */
|
||||
#define IGP01IGC_PHY_PORT_CTRL 0x12 /* Control */
|
||||
#define IGP01IGC_PHY_LINK_HEALTH 0x13 /* PHY Link Health */
|
||||
#define IGP02IGC_PHY_POWER_MGMT 0x19 /* Power Management */
|
||||
#define IGP01IGC_PHY_PAGE_SELECT 0x1F /* Page Select */
|
||||
#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */
|
||||
#define IGP_PAGE_SHIFT 5
|
||||
#define PHY_REG_MASK 0x1F
|
||||
#define IGC_I225_PHPM 0x0E14 /* I225 PHY Power Management */
|
||||
#define IGC_I225_PHPM_DIS_1000_D3 0x0008 /* Disable 1G in D3 */
|
||||
#define IGC_I225_PHPM_LINK_ENERGY 0x0010 /* Link Energy Detect */
|
||||
#define IGC_I225_PHPM_GO_LINKD 0x0020 /* Go Link Disconnect */
|
||||
#define IGC_I225_PHPM_DIS_1000 0x0040 /* Disable 1G globally */
|
||||
#define IGC_I225_PHPM_SPD_B2B_EN 0x0080 /* Smart Power Down Back2Back */
|
||||
#define IGC_I225_PHPM_RST_COMPL 0x0100 /* PHY Reset Completed */
|
||||
#define IGC_I225_PHPM_DIS_100_D3 0x0200 /* Disable 100M in D3 */
|
||||
#define IGC_I225_PHPM_ULP 0x0400 /* Ultra Low-Power Mode */
|
||||
#define IGC_I225_PHPM_DIS_2500 0x0800 /* Disable 2.5G globally */
|
||||
#define IGC_I225_PHPM_DIS_2500_D3 0x1000 /* Disable 2.5G in D3 */
|
||||
/* GPY211 - I225 defines */
|
||||
#define GPY_MMD_MASK 0xFFFF0000
|
||||
#define GPY_MMD_SHIFT 16
|
||||
#define GPY_REG_MASK 0x0000FFFF
|
||||
#define IGP01IGC_PHY_PCS_INIT_REG 0x00B4
|
||||
#define IGP01IGC_PHY_POLARITY_MASK 0x0078
|
||||
|
||||
#define IGP01IGC_PSCR_AUTO_MDIX 0x1000
|
||||
#define IGP01IGC_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
|
||||
|
||||
#define IGP01IGC_PSCFR_SMART_SPEED 0x0080
|
||||
|
||||
#define IGP02IGC_PM_SPD 0x0001 /* Smart Power Down */
|
||||
#define IGP02IGC_PM_D0_LPLU 0x0002 /* For D0a states */
|
||||
#define IGP02IGC_PM_D3_LPLU 0x0004 /* For all other states */
|
||||
|
||||
#define IGP01IGC_PLHR_SS_DOWNGRADE 0x8000
|
||||
|
||||
#define IGP01IGC_PSSR_POLARITY_REVERSED 0x0002
|
||||
#define IGP01IGC_PSSR_MDIX 0x0800
|
||||
#define IGP01IGC_PSSR_SPEED_MASK 0xC000
|
||||
#define IGP01IGC_PSSR_SPEED_1000MBPS 0xC000
|
||||
|
||||
#define IGP02IGC_PHY_CHANNEL_NUM 4
|
||||
#define IGP02IGC_PHY_AGC_A 0x11B1
|
||||
#define IGP02IGC_PHY_AGC_B 0x12B1
|
||||
#define IGP02IGC_PHY_AGC_C 0x14B1
|
||||
#define IGP02IGC_PHY_AGC_D 0x18B1
|
||||
|
||||
#define IGP02IGC_AGC_LENGTH_SHIFT 9 /* Course=15:13, Fine=12:9 */
|
||||
#define IGP02IGC_AGC_LENGTH_MASK 0x7F
|
||||
#define IGP02IGC_AGC_RANGE 15
|
||||
|
||||
#define IGC_CABLE_LENGTH_UNDEFINED 0xFF
|
||||
|
||||
#define IGC_KMRNCTRLSTA_OFFSET 0x001F0000
|
||||
#define IGC_KMRNCTRLSTA_OFFSET_SHIFT 16
|
||||
#define IGC_KMRNCTRLSTA_REN 0x00200000
|
||||
#define IGC_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
|
||||
#define IGC_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
|
||||
#define IGC_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
|
||||
#define IGC_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */
|
||||
#define IGC_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
|
||||
|
||||
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
|
||||
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */
|
||||
#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Ctrl */
|
||||
#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */
|
||||
|
||||
/* IFE PHY Extended Status Control */
|
||||
#define IFE_PESC_POLARITY_REVERSED 0x0100
|
||||
|
||||
/* IFE PHY Special Control */
|
||||
#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010
|
||||
#define IFE_PSC_FORCE_POLARITY 0x0020
|
||||
|
||||
/* IFE PHY Special Control and LED Control */
|
||||
#define IFE_PSCL_PROBE_MODE 0x0020
|
||||
#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */
|
||||
#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */
|
||||
|
||||
/* IFE PHY MDIX Control */
|
||||
#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */
|
||||
#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */
|
||||
#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto, 0=disable */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,424 @@
|
||||
/*-
|
||||
* Copyright 2021 Intel Corp
|
||||
* Copyright 2021 Rubicon Communications, LLC (Netgate)
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _IGC_REGS_H_
|
||||
#define _IGC_REGS_H_
|
||||
|
||||
/* General Register Descriptions */
|
||||
#define IGC_CTRL 0x00000 /* Device Control - RW */
|
||||
#define IGC_STATUS 0x00008 /* Device Status - RO */
|
||||
#define IGC_EECD 0x00010 /* EEPROM/Flash Control - RW */
|
||||
/* NVM Register Descriptions */
|
||||
#define IGC_EERD 0x12014 /* EEprom mode read - RW */
|
||||
#define IGC_EEWR 0x12018 /* EEprom mode write - RW */
|
||||
#define IGC_CTRL_EXT 0x00018 /* Extended Device Control - RW */
|
||||
#define IGC_MDIC 0x00020 /* MDI Control - RW */
|
||||
#define IGC_MDICNFG 0x00E04 /* MDI Config - RW */
|
||||
#define IGC_FCAL 0x00028 /* Flow Control Address Low - RW */
|
||||
#define IGC_FCAH 0x0002C /* Flow Control Address High -RW */
|
||||
#define IGC_I225_FLSWCTL 0x12048 /* FLASH control register */
|
||||
#define IGC_I225_FLSWDATA 0x1204C /* FLASH data register */
|
||||
#define IGC_I225_FLSWCNT 0x12050 /* FLASH Access Counter */
|
||||
#define IGC_I225_FLSECU 0x12114 /* FLASH Security */
|
||||
#define IGC_FCT 0x00030 /* Flow Control Type - RW */
|
||||
#define IGC_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
|
||||
#define IGC_VET 0x00038 /* VLAN Ether Type - RW */
|
||||
#define IGC_ICR 0x01500 /* Intr Cause Read - RC/W1C */
|
||||
#define IGC_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
|
||||
#define IGC_ICS 0x01504 /* Intr Cause Set - WO */
|
||||
#define IGC_IMS 0x01508 /* Intr Mask Set/Read - RW */
|
||||
#define IGC_IMC 0x0150C /* Intr Mask Clear - WO */
|
||||
#define IGC_IAM 0x01510 /* Intr Ack Auto Mask- RW */
|
||||
#define IGC_RCTL 0x00100 /* Rx Control - RW */
|
||||
#define IGC_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
|
||||
#define IGC_TXCW 0x00178 /* Tx Configuration Word - RW */
|
||||
#define IGC_RXCW 0x00180 /* Rx Configuration Word - RO */
|
||||
#define IGC_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
|
||||
#define IGC_EITR(_n) (0x01680 + (0x4 * (_n)))
|
||||
#define IGC_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
|
||||
#define IGC_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
|
||||
#define IGC_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
|
||||
#define IGC_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
|
||||
#define IGC_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
|
||||
#define IGC_GPIE 0x01514 /* General Purpose Interrupt Enable - RW */
|
||||
#define IGC_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
|
||||
#define IGC_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
|
||||
#define IGC_TCTL 0x00400 /* Tx Control - RW */
|
||||
#define IGC_TCTL_EXT 0x00404 /* Extended Tx Control - RW */
|
||||
#define IGC_TIPG 0x00410 /* Tx Inter-packet gap -RW */
|
||||
#define IGC_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
|
||||
#define IGC_LEDCTL 0x00E00 /* LED Control - RW */
|
||||
#define IGC_LEDMUX 0x08130 /* LED MUX Control */
|
||||
#define IGC_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
|
||||
#define IGC_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
|
||||
#define IGC_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */
|
||||
#define IGC_PBA 0x01000 /* Packet Buffer Allocation - RW */
|
||||
#define IGC_PBS 0x01008 /* Packet Buffer Size */
|
||||
#define IGC_EEMNGCTL 0x01010 /* MNG EEprom Control */
|
||||
#define IGC_EEMNGCTL_I225 0x01010 /* i225 MNG EEprom Mode Control */
|
||||
#define IGC_EEARBC_I225 0x12024 /* EEPROM Auto Read Bus Control */
|
||||
#define IGC_FLOP 0x0103C /* FLASH Opcode Register */
|
||||
#define IGC_WDSTP 0x01040 /* Watchdog Setup - RW */
|
||||
#define IGC_SWDSTS 0x01044 /* SW Device Status - RW */
|
||||
#define IGC_FRTIMER 0x01048 /* Free Running Timer - RW */
|
||||
#define IGC_TCPTIMER 0x0104C /* TCP Timer - RW */
|
||||
#define IGC_ERT 0x02008 /* Early Rx Threshold - RW */
|
||||
#define IGC_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
|
||||
#define IGC_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
|
||||
#define IGC_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
|
||||
#define IGC_RDFH 0x02410 /* Rx Data FIFO Head - RW */
|
||||
#define IGC_RDFT 0x02418 /* Rx Data FIFO Tail - RW */
|
||||
#define IGC_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */
|
||||
#define IGC_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */
|
||||
#define IGC_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */
|
||||
#define IGC_PBRTH 0x02458 /* PB Rx Arbitration Threshold - RW */
|
||||
#define IGC_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
|
||||
/* Split and Replication Rx Control - RW */
|
||||
#define IGC_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
|
||||
#define IGC_RDTR 0x02820 /* Rx Delay Timer - RW */
|
||||
#define IGC_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */
|
||||
/* Shadow Ram Write Register - RW */
|
||||
#define IGC_SRWR 0x12018
|
||||
#define IGC_EEC_REG 0x12010
|
||||
|
||||
|
||||
#define IGC_SHADOWINF 0x12068
|
||||
#define IGC_FLFWUPDATE 0x12108
|
||||
|
||||
#define IGC_INVM_DATA_REG(_n) (0x12120 + 4*(_n))
|
||||
#define IGC_INVM_SIZE 64 /* Number of INVM Data Registers */
|
||||
|
||||
#define IGC_MMDAC 13 /* MMD Access Control */
|
||||
#define IGC_MMDAAD 14 /* MMD Access Address/Data */
|
||||
/* Convenience macros
|
||||
*
|
||||
* Note: "_n" is the queue number of the register to be written to.
|
||||
*
|
||||
* Example usage:
|
||||
* IGC_RDBAL_REG(current_rx_queue)
|
||||
*/
|
||||
#define IGC_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
|
||||
(0x0C000 + ((_n) * 0x40)))
|
||||
#define IGC_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
|
||||
(0x0C004 + ((_n) * 0x40)))
|
||||
#define IGC_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
|
||||
(0x0C008 + ((_n) * 0x40)))
|
||||
#define IGC_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
|
||||
(0x0C00C + ((_n) * 0x40)))
|
||||
#define IGC_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
|
||||
(0x0C010 + ((_n) * 0x40)))
|
||||
#define IGC_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
|
||||
(0x0C018 + ((_n) * 0x40)))
|
||||
#define IGC_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
|
||||
(0x0C028 + ((_n) * 0x40)))
|
||||
#define IGC_RQDPC(_n) ((_n) < 4 ? (0x02830 + ((_n) * 0x100)) : \
|
||||
(0x0C030 + ((_n) * 0x40)))
|
||||
#define IGC_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
|
||||
(0x0E000 + ((_n) * 0x40)))
|
||||
#define IGC_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
|
||||
(0x0E004 + ((_n) * 0x40)))
|
||||
#define IGC_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
|
||||
(0x0E008 + ((_n) * 0x40)))
|
||||
#define IGC_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
|
||||
(0x0E010 + ((_n) * 0x40)))
|
||||
#define IGC_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
|
||||
(0x0E018 + ((_n) * 0x40)))
|
||||
#define IGC_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
|
||||
(0x0E028 + ((_n) * 0x40)))
|
||||
#define IGC_TARC(_n) (0x03840 + ((_n) * 0x100))
|
||||
#define IGC_RSRPD 0x02C00 /* Rx Small Packet Detect - RW */
|
||||
#define IGC_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
|
||||
#define IGC_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */
|
||||
#define IGC_PSRTYPE(_i) (0x05480 + ((_i) * 4))
|
||||
#define IGC_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
|
||||
(0x054E0 + ((_i - 16) * 8)))
|
||||
#define IGC_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
|
||||
(0x054E4 + ((_i - 16) * 8)))
|
||||
#define IGC_VLANPQF 0x055B0 /* VLAN Priority Queue Filter VLAPQF */
|
||||
|
||||
#define IGC_SHRAL(_i) (0x05438 + ((_i) * 8))
|
||||
#define IGC_SHRAH(_i) (0x0543C + ((_i) * 8))
|
||||
#define IGC_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
|
||||
#define IGC_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
|
||||
#define IGC_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
|
||||
#define IGC_FFMT_REG(_i) (0x09000 + ((_i) * 8))
|
||||
#define IGC_FFVT_REG(_i) (0x09800 + ((_i) * 8))
|
||||
#define IGC_FFLT_REG(_i) (0x05F00 + ((_i) * 8))
|
||||
#define IGC_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */
|
||||
#define IGC_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */
|
||||
#define IGC_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */
|
||||
/* Statistics Register Descriptions */
|
||||
#define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */
|
||||
#define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
|
||||
#define IGC_MPC 0x04010 /* Missed Packet Count - R/clr */
|
||||
#define IGC_SCC 0x04014 /* Single Collision Count - R/clr */
|
||||
#define IGC_ECOL 0x04018 /* Excessive Collision Count - R/clr */
|
||||
#define IGC_MCC 0x0401C /* Multiple Collision Count - R/clr */
|
||||
#define IGC_LATECOL 0x04020 /* Late Collision Count - R/clr */
|
||||
#define IGC_COLC 0x04028 /* Collision Count - R/clr */
|
||||
#define IGC_RERC 0x0402C /* Receive Error Count - R/clr */
|
||||
#define IGC_DC 0x04030 /* Defer Count - R/clr */
|
||||
#define IGC_TNCRS 0x04034 /* Tx-No CRS - R/clr */
|
||||
#define IGC_HTDPMC 0x0403C /* Host Transmit Discarded by MAC - R/clr */
|
||||
#define IGC_RLEC 0x04040 /* Receive Length Error Count - R/clr */
|
||||
#define IGC_XONRXC 0x04048 /* XON Rx Count - R/clr */
|
||||
#define IGC_XONTXC 0x0404C /* XON Tx Count - R/clr */
|
||||
#define IGC_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
|
||||
#define IGC_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
|
||||
#define IGC_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
|
||||
#define IGC_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
|
||||
#define IGC_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
|
||||
#define IGC_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
|
||||
#define IGC_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
|
||||
#define IGC_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
|
||||
#define IGC_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
|
||||
#define IGC_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
|
||||
#define IGC_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
|
||||
#define IGC_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
|
||||
#define IGC_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
|
||||
#define IGC_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
|
||||
#define IGC_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
|
||||
#define IGC_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
|
||||
#define IGC_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
|
||||
#define IGC_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
|
||||
#define IGC_RUC 0x040A4 /* Rx Undersize Count - R/clr */
|
||||
#define IGC_RFC 0x040A8 /* Rx Fragment Count - R/clr */
|
||||
#define IGC_ROC 0x040AC /* Rx Oversize Count - R/clr */
|
||||
#define IGC_RJC 0x040B0 /* Rx Jabber Count - R/clr */
|
||||
#define IGC_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
|
||||
#define IGC_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
|
||||
#define IGC_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
|
||||
#define IGC_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
|
||||
#define IGC_TORH 0x040C4 /* Total Octets Rx High - R/clr */
|
||||
#define IGC_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
|
||||
#define IGC_TOTH 0x040CC /* Total Octets Tx High - R/clr */
|
||||
#define IGC_TPR 0x040D0 /* Total Packets Rx - R/clr */
|
||||
#define IGC_TPT 0x040D4 /* Total Packets Tx - R/clr */
|
||||
#define IGC_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
|
||||
#define IGC_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
|
||||
#define IGC_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
|
||||
#define IGC_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
|
||||
#define IGC_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
|
||||
#define IGC_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
|
||||
#define IGC_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
|
||||
#define IGC_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
|
||||
#define IGC_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
|
||||
#define IGC_IAC 0x04100 /* Interrupt Assertion Count */
|
||||
#define IGC_RXDMTC 0x04120 /* Rx Descriptor Minimum Threshold Count */
|
||||
|
||||
#define IGC_VFGPRC 0x00F10
|
||||
#define IGC_VFGORC 0x00F18
|
||||
#define IGC_VFMPRC 0x00F3C
|
||||
#define IGC_VFGPTC 0x00F14
|
||||
#define IGC_VFGOTC 0x00F34
|
||||
#define IGC_VFGOTLBC 0x00F50
|
||||
#define IGC_VFGPTLBC 0x00F44
|
||||
#define IGC_VFGORLBC 0x00F48
|
||||
#define IGC_VFGPRLBC 0x00F40
|
||||
#define IGC_HGORCL 0x04128 /* Host Good Octets Received Count Low */
|
||||
#define IGC_HGORCH 0x0412C /* Host Good Octets Received Count High */
|
||||
#define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
|
||||
#define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
|
||||
#define IGC_LENERRS 0x04138 /* Length Errors Count */
|
||||
#define IGC_PCS_ANADV 0x04218 /* AN advertisement - RW */
|
||||
#define IGC_PCS_LPAB 0x0421C /* Link Partner Ability - RW */
|
||||
#define IGC_RXCSUM 0x05000 /* Rx Checksum Control - RW */
|
||||
#define IGC_RLPML 0x05004 /* Rx Long Packet Max Length */
|
||||
#define IGC_RFCTL 0x05008 /* Receive Filter Control*/
|
||||
#define IGC_MTA 0x05200 /* Multicast Table Array - RW Array */
|
||||
#define IGC_RA 0x05400 /* Receive Address - RW Array */
|
||||
#define IGC_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
|
||||
#define IGC_WUC 0x05800 /* Wakeup Control - RW */
|
||||
#define IGC_WUFC 0x05808 /* Wakeup Filter Control - RW */
|
||||
#define IGC_WUS 0x05810 /* Wakeup Status - RO */
|
||||
/* Management registers */
|
||||
#define IGC_MANC 0x05820 /* Management Control - RW */
|
||||
#define IGC_IPAV 0x05838 /* IP Address Valid - RW */
|
||||
#define IGC_IP4AT 0x05840 /* IPv4 Address Table - RW Array */
|
||||
#define IGC_IP6AT 0x05880 /* IPv6 Address Table - RW Array */
|
||||
#define IGC_WUPL 0x05900 /* Wakeup Packet Length - RW */
|
||||
#define IGC_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */
|
||||
#define IGC_WUPM_EXT 0x0B800 /* Wakeup Packet Memory Extended - RO Array */
|
||||
#define IGC_WUFC_EXT 0x0580C /* Wakeup Filter Control Extended - RW */
|
||||
#define IGC_WUS_EXT 0x05814 /* Wakeup Status Extended - RW1C */
|
||||
#define IGC_FHFTSL 0x05804 /* Flex Filter Indirect Table Select - RW */
|
||||
#define IGC_PROXYFCEX 0x05590 /* Proxy Filter Control Extended - RW1C */
|
||||
#define IGC_PROXYEXS 0x05594 /* Proxy Extended Status - RO */
|
||||
#define IGC_WFUTPF 0x05500 /* Wake Flex UDP TCP Port Filter - RW Array */
|
||||
#define IGC_RFUTPF 0x05580 /* Range Flex UDP TCP Port Filter - RW */
|
||||
#define IGC_RWPFC 0x05584 /* Range Wake Port Filter Control - RW */
|
||||
#define IGC_WFUTPS 0x05588 /* Wake Filter UDP TCP Status - RW1C */
|
||||
#define IGC_WCS 0x0558C /* Wake Control Status - RW1C */
|
||||
/* MSI-X Table Register Descriptions */
|
||||
#define IGC_PBACL 0x05B68 /* MSIx PBA Clear - Read/Write 1's to clear */
|
||||
#define IGC_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */
|
||||
#define IGC_HOST_IF 0x08800 /* Host Interface */
|
||||
/* Flexible Host Filter Table */
|
||||
#define IGC_FHFT(_n) (0x09000 + ((_n) * 0x100))
|
||||
/* Ext Flexible Host Filter Table */
|
||||
#define IGC_FHFT_EXT(_n) (0x09A00 + ((_n) * 0x100))
|
||||
|
||||
|
||||
#define IGC_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */
|
||||
#define IGC_MANC2H 0x05860 /* Management Control To Host - RW */
|
||||
/* Management Decision Filters */
|
||||
#define IGC_MDEF(_n) (0x05890 + (4 * (_n)))
|
||||
/* Semaphore registers */
|
||||
#define IGC_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */
|
||||
/* Function Active and Power State to MNG */
|
||||
#define IGC_FACTPS 0x05B30
|
||||
#define IGC_SWSM 0x05B50 /* SW Semaphore */
|
||||
#define IGC_FWSM 0x05B54 /* FW Semaphore */
|
||||
/* Driver-only SW semaphore (not used by BOOT agents) */
|
||||
#define IGC_SWSM2 0x05B58
|
||||
#define IGC_FFLT_DBG 0x05F04 /* Debug Register */
|
||||
#define IGC_HICR 0x08F00 /* Host Interface Control */
|
||||
#define IGC_FWSTS 0x08F0C /* FW Status */
|
||||
|
||||
/* RSS registers */
|
||||
#define IGC_MRQC 0x05818 /* Multiple Receive Control - RW */
|
||||
#define IGC_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
|
||||
#define IGC_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/
|
||||
#define IGC_IMIRVP 0x05AC0 /* Immediate INT Rx VLAN Priority -RW */
|
||||
#define IGC_MSIXBM(_i) (0x01600 + ((_i) * 4)) /* MSI-X Alloc Reg -RW */
|
||||
/* Redirection Table - RW Array */
|
||||
#define IGC_RETA(_i) (0x05C00 + ((_i) * 4))
|
||||
/* RSS Random Key - RW Array */
|
||||
#define IGC_RSSRK(_i) (0x05C80 + ((_i) * 4))
|
||||
#define IGC_RSSIM 0x05864 /* RSS Interrupt Mask */
|
||||
#define IGC_RSSIR 0x05868 /* RSS Interrupt Request */
|
||||
#define IGC_UTA 0x0A000 /* Unicast Table Array - RW */
|
||||
#define IGC_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
|
||||
#define IGC_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
|
||||
#define IGC_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
|
||||
#define IGC_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */
|
||||
#define IGC_RXSTMPH 0x0B628 /* Rx timestamp High - RO */
|
||||
#define IGC_RXSATRL 0x0B62C /* Rx timestamp attribute low - RO */
|
||||
#define IGC_RXSATRH 0x0B630 /* Rx timestamp attribute high - RO */
|
||||
#define IGC_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
|
||||
#define IGC_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
|
||||
#define IGC_SYSTIML 0x0B600 /* System time register Low - RO */
|
||||
#define IGC_SYSTIMH 0x0B604 /* System time register High - RO */
|
||||
#define IGC_TIMINCA 0x0B608 /* Increment attributes register - RW */
|
||||
#define IGC_TIMADJL 0x0B60C /* Time sync time adjustment offset Low - RW */
|
||||
#define IGC_TIMADJH 0x0B610 /* Time sync time adjustment offset High - RW */
|
||||
#define IGC_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
|
||||
#define IGC_SYSTIMR 0x0B6F8 /* System time register Residue */
|
||||
#define IGC_TSICR 0x0B66C /* Interrupt Cause Register */
|
||||
#define IGC_TSIM 0x0B674 /* Interrupt Mask Register */
|
||||
|
||||
/* Filtering Registers */
|
||||
#define IGC_SAQF(_n) (0x05980 + (4 * (_n))) /* Source Address Queue Fltr */
|
||||
#define IGC_DAQF(_n) (0x059A0 + (4 * (_n))) /* Dest Address Queue Fltr */
|
||||
#define IGC_SPQF(_n) (0x059C0 + (4 * (_n))) /* Source Port Queue Fltr */
|
||||
#define IGC_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */
|
||||
#define IGC_TTQF(_n) (0x059E0 + (4 * (_n))) /* 2-tuple Queue Fltr */
|
||||
#define IGC_SYNQF(_n) (0x055FC + (4 * (_n))) /* SYN Packet Queue Fltr */
|
||||
#define IGC_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
|
||||
|
||||
/* ETQF register bit definitions */
|
||||
#define IGC_ETQF_FILTER_ENABLE (1 << 26)
|
||||
#define IGC_ETQF_IMM_INT (1 << 29)
|
||||
#define IGC_ETQF_QUEUE_ENABLE (1 << 31)
|
||||
#define IGC_ETQF_QUEUE_SHIFT 16
|
||||
#define IGC_ETQF_QUEUE_MASK 0x00070000
|
||||
#define IGC_ETQF_ETYPE_MASK 0x0000FFFF
|
||||
|
||||
#define IGC_RTTDCS 0x3600 /* Reedtown Tx Desc plane control and status */
|
||||
#define IGC_RTTPCS 0x3474 /* Reedtown Tx Packet Plane control and status */
|
||||
#define IGC_RTRPCS 0x2474 /* Rx packet plane control and status */
|
||||
#define IGC_RTRUP2TC 0x05AC4 /* Rx User Priority to Traffic Class */
|
||||
#define IGC_RTTUP2TC 0x0418 /* Transmit User Priority to Traffic Class */
|
||||
/* Tx Desc plane TC Rate-scheduler config */
|
||||
#define IGC_RTTDTCRC(_n) (0x3610 + ((_n) * 4))
|
||||
/* Tx Packet plane TC Rate-Scheduler Config */
|
||||
#define IGC_RTTPTCRC(_n) (0x3480 + ((_n) * 4))
|
||||
/* Rx Packet plane TC Rate-Scheduler Config */
|
||||
#define IGC_RTRPTCRC(_n) (0x2480 + ((_n) * 4))
|
||||
/* Tx Desc Plane TC Rate-Scheduler Status */
|
||||
#define IGC_RTTDTCRS(_n) (0x3630 + ((_n) * 4))
|
||||
/* Tx Desc Plane TC Rate-Scheduler MMW */
|
||||
#define IGC_RTTDTCRM(_n) (0x3650 + ((_n) * 4))
|
||||
/* Tx Packet plane TC Rate-Scheduler Status */
|
||||
#define IGC_RTTPTCRS(_n) (0x34A0 + ((_n) * 4))
|
||||
/* Tx Packet plane TC Rate-scheduler MMW */
|
||||
#define IGC_RTTPTCRM(_n) (0x34C0 + ((_n) * 4))
|
||||
/* Rx Packet plane TC Rate-Scheduler Status */
|
||||
#define IGC_RTRPTCRS(_n) (0x24A0 + ((_n) * 4))
|
||||
/* Rx Packet plane TC Rate-Scheduler MMW */
|
||||
#define IGC_RTRPTCRM(_n) (0x24C0 + ((_n) * 4))
|
||||
/* Tx Desc plane VM Rate-Scheduler MMW*/
|
||||
#define IGC_RTTDVMRM(_n) (0x3670 + ((_n) * 4))
|
||||
/* Tx BCN Rate-Scheduler MMW */
|
||||
#define IGC_RTTBCNRM(_n) (0x3690 + ((_n) * 4))
|
||||
#define IGC_RTTDQSEL 0x3604 /* Tx Desc Plane Queue Select */
|
||||
#define IGC_RTTDVMRC 0x3608 /* Tx Desc Plane VM Rate-Scheduler Config */
|
||||
#define IGC_RTTDVMRS 0x360C /* Tx Desc Plane VM Rate-Scheduler Status */
|
||||
#define IGC_RTTBCNRC 0x36B0 /* Tx BCN Rate-Scheduler Config */
|
||||
#define IGC_RTTBCNRS 0x36B4 /* Tx BCN Rate-Scheduler Status */
|
||||
#define IGC_RTTBCNCR 0xB200 /* Tx BCN Control Register */
|
||||
#define IGC_RTTBCNTG 0x35A4 /* Tx BCN Tagging */
|
||||
#define IGC_RTTBCNCP 0xB208 /* Tx BCN Congestion point */
|
||||
#define IGC_RTRBCNCR 0xB20C /* Rx BCN Control Register */
|
||||
#define IGC_RTTBCNRD 0x36B8 /* Tx BCN Rate Drift */
|
||||
#define IGC_PFCTOP 0x1080 /* Priority Flow Control Type and Opcode */
|
||||
#define IGC_RTTBCNIDX 0xB204 /* Tx BCN Congestion Point */
|
||||
#define IGC_RTTBCNACH 0x0B214 /* Tx BCN Control High */
|
||||
#define IGC_RTTBCNACL 0x0B210 /* Tx BCN Control Low */
|
||||
|
||||
/* DMA Coalescing registers */
|
||||
#define IGC_DMACR 0x02508 /* Control Register */
|
||||
#define IGC_DMCTXTH 0x03550 /* Transmit Threshold */
|
||||
#define IGC_DMCTLX 0x02514 /* Time to Lx Request */
|
||||
#define IGC_DMCRTRH 0x05DD0 /* Receive Packet Rate Threshold */
|
||||
#define IGC_DMCCNT 0x05DD4 /* Current Rx Count */
|
||||
#define IGC_FCRTC 0x02170 /* Flow Control Rx high watermark */
|
||||
#define IGC_PCIEMISC 0x05BB8 /* PCIE misc config register */
|
||||
|
||||
/* PCIe Parity Status Register */
|
||||
#define IGC_PCIEERRSTS 0x05BA8
|
||||
|
||||
#define IGC_PROXYS 0x5F64 /* Proxying Status */
|
||||
#define IGC_PROXYFC 0x5F60 /* Proxying Filter Control */
|
||||
/* Thermal sensor configuration and status registers */
|
||||
#define IGC_THMJT 0x08100 /* Junction Temperature */
|
||||
#define IGC_THLOWTC 0x08104 /* Low Threshold Control */
|
||||
#define IGC_THMIDTC 0x08108 /* Mid Threshold Control */
|
||||
#define IGC_THHIGHTC 0x0810C /* High Threshold Control */
|
||||
#define IGC_THSTAT 0x08110 /* Thermal Sensor Status */
|
||||
|
||||
/* Energy Efficient Ethernet "EEE" registers */
|
||||
#define IGC_IPCNFG 0x0E38 /* Internal PHY Configuration */
|
||||
#define IGC_LTRC 0x01A0 /* Latency Tolerance Reporting Control */
|
||||
#define IGC_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/
|
||||
#define IGC_EEE_SU 0x0E34 /* EEE Setup */
|
||||
#define IGC_EEE_SU_2P5 0x0E3C /* EEE 2.5G Setup */
|
||||
#define IGC_TLPIC 0x4148 /* EEE Tx LPI Count - TLPIC */
|
||||
#define IGC_RLPIC 0x414C /* EEE Rx LPI Count - RLPIC */
|
||||
|
||||
/* OS2BMC Registers */
|
||||
#define IGC_B2OSPC 0x08FE0 /* BMC2OS packets sent by BMC */
|
||||
#define IGC_B2OGPRC 0x04158 /* BMC2OS packets received by host */
|
||||
#define IGC_O2BGPTC 0x08FE4 /* OS2BMC packets received by BMC */
|
||||
#define IGC_O2BSPC 0x0415C /* OS2BMC packets transmitted by host */
|
||||
|
||||
#define IGC_LTRMINV 0x5BB0 /* LTR Minimum Value */
|
||||
#define IGC_LTRMAXV 0x5BB4 /* LTR Maximum Value */
|
||||
|
||||
|
||||
/* IEEE 1588 TIMESYNCH */
|
||||
#define IGC_TRGTTIML0 0x0B644 /* Target Time Register 0 Low - RW */
|
||||
#define IGC_TRGTTIMH0 0x0B648 /* Target Time Register 0 High - RW */
|
||||
#define IGC_TRGTTIML1 0x0B64C /* Target Time Register 1 Low - RW */
|
||||
#define IGC_TRGTTIMH1 0x0B650 /* Target Time Register 1 High - RW */
|
||||
#define IGC_FREQOUT0 0x0B654 /* Frequency Out 0 Control Register - RW */
|
||||
#define IGC_FREQOUT1 0x0B658 /* Frequency Out 1 Control Register - RW */
|
||||
#define IGC_TSSDP 0x0003C /* Time Sync SDP Configuration Register - RW */
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,596 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io>
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "if_igc.h"
|
||||
|
||||
#ifdef RSS
|
||||
#include <net/rss_config.h>
|
||||
#include <netinet/in_rss.h>
|
||||
#endif
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
#define DPRINTF device_printf
|
||||
#else
|
||||
#define DPRINTF(...)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
* Local Function prototypes
|
||||
*********************************************************************/
|
||||
static int igc_isc_txd_encap(void *arg, if_pkt_info_t pi);
|
||||
static void igc_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx);
|
||||
static int igc_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear);
|
||||
|
||||
static void igc_isc_rxd_refill(void *arg, if_rxd_update_t iru);
|
||||
|
||||
static void igc_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused,
|
||||
qidx_t pidx);
|
||||
static int igc_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx,
|
||||
qidx_t budget);
|
||||
|
||||
static int igc_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri);
|
||||
|
||||
static int igc_tx_ctx_setup(struct tx_ring *txr, if_pkt_info_t pi,
|
||||
uint32_t *cmd_type_len, uint32_t *olinfo_status);
|
||||
static int igc_tso_setup(struct tx_ring *txr, if_pkt_info_t pi,
|
||||
uint32_t *cmd_type_len, uint32_t *olinfo_status);
|
||||
|
||||
static void igc_rx_checksum(uint32_t staterr, if_rxd_info_t ri, uint32_t ptype);
|
||||
static int igc_determine_rsstype(uint16_t pkt_info);
|
||||
|
||||
extern void igc_if_enable_intr(if_ctx_t ctx);
|
||||
extern int igc_intr(void *arg);
|
||||
|
||||
struct if_txrx igc_txrx = {
|
||||
.ift_txd_encap = igc_isc_txd_encap,
|
||||
.ift_txd_flush = igc_isc_txd_flush,
|
||||
.ift_txd_credits_update = igc_isc_txd_credits_update,
|
||||
.ift_rxd_available = igc_isc_rxd_available,
|
||||
.ift_rxd_pkt_get = igc_isc_rxd_pkt_get,
|
||||
.ift_rxd_refill = igc_isc_rxd_refill,
|
||||
.ift_rxd_flush = igc_isc_rxd_flush,
|
||||
.ift_legacy_intr = igc_intr
|
||||
};
|
||||
|
||||
void
|
||||
igc_dump_rs(struct igc_adapter *adapter)
|
||||
{
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct igc_tx_queue *que;
|
||||
struct tx_ring *txr;
|
||||
qidx_t i, ntxd, qid, cur;
|
||||
int16_t rs_cidx;
|
||||
uint8_t status;
|
||||
|
||||
printf("\n");
|
||||
ntxd = scctx->isc_ntxd[0];
|
||||
for (qid = 0; qid < adapter->tx_num_queues; qid++) {
|
||||
que = &adapter->tx_queues[qid];
|
||||
txr = &que->txr;
|
||||
rs_cidx = txr->tx_rs_cidx;
|
||||
if (rs_cidx != txr->tx_rs_pidx) {
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
status = txr->tx_base[cur].upper.fields.status;
|
||||
if (!(status & IGC_TXD_STAT_DD))
|
||||
printf("qid[%d]->tx_rsq[%d]: %d clear ", qid, rs_cidx, cur);
|
||||
} else {
|
||||
rs_cidx = (rs_cidx-1)&(ntxd-1);
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
printf("qid[%d]->tx_rsq[rs_cidx-1=%d]: %d ", qid, rs_cidx, cur);
|
||||
}
|
||||
printf("cidx_prev=%d rs_pidx=%d ",txr->tx_cidx_processed, txr->tx_rs_pidx);
|
||||
for (i = 0; i < ntxd; i++) {
|
||||
if (txr->tx_base[i].upper.fields.status & IGC_TXD_STAT_DD)
|
||||
printf("%d set ", i);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
*
|
||||
* Setup work for hardware segmentation offload (TSO) on
|
||||
* adapters using advanced tx descriptors
|
||||
*
|
||||
**********************************************************************/
|
||||
static int
|
||||
igc_tso_setup(struct tx_ring *txr, if_pkt_info_t pi, uint32_t *cmd_type_len,
|
||||
uint32_t *olinfo_status)
|
||||
{
|
||||
struct igc_adv_tx_context_desc *TXD;
|
||||
uint32_t type_tucmd_mlhl = 0, vlan_macip_lens = 0;
|
||||
uint32_t mss_l4len_idx = 0;
|
||||
uint32_t paylen;
|
||||
|
||||
switch(pi->ipi_etype) {
|
||||
case ETHERTYPE_IPV6:
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV6;
|
||||
break;
|
||||
case ETHERTYPE_IP:
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV4;
|
||||
/* Tell transmit desc to also do IPv4 checksum. */
|
||||
*olinfo_status |= IGC_TXD_POPTS_IXSM << 8;
|
||||
break;
|
||||
default:
|
||||
panic("%s: CSUM_TSO but no supported IP version (0x%04x)",
|
||||
__func__, ntohs(pi->ipi_etype));
|
||||
break;
|
||||
}
|
||||
|
||||
TXD = (struct igc_adv_tx_context_desc *) &txr->tx_base[pi->ipi_pidx];
|
||||
|
||||
/* This is used in the transmit desc in encap */
|
||||
paylen = pi->ipi_len - pi->ipi_ehdrlen - pi->ipi_ip_hlen - pi->ipi_tcp_hlen;
|
||||
|
||||
/* VLAN MACLEN IPLEN */
|
||||
if (pi->ipi_mflags & M_VLANTAG) {
|
||||
vlan_macip_lens |= (pi->ipi_vtag << IGC_ADVTXD_VLAN_SHIFT);
|
||||
}
|
||||
|
||||
vlan_macip_lens |= pi->ipi_ehdrlen << IGC_ADVTXD_MACLEN_SHIFT;
|
||||
vlan_macip_lens |= pi->ipi_ip_hlen;
|
||||
TXD->vlan_macip_lens = htole32(vlan_macip_lens);
|
||||
|
||||
/* ADV DTYPE TUCMD */
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_DCMD_DEXT | IGC_ADVTXD_DTYP_CTXT;
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_L4T_TCP;
|
||||
TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
|
||||
|
||||
/* MSS L4LEN IDX */
|
||||
mss_l4len_idx |= (pi->ipi_tso_segsz << IGC_ADVTXD_MSS_SHIFT);
|
||||
mss_l4len_idx |= (pi->ipi_tcp_hlen << IGC_ADVTXD_L4LEN_SHIFT);
|
||||
TXD->mss_l4len_idx = htole32(mss_l4len_idx);
|
||||
|
||||
TXD->seqnum_seed = htole32(0);
|
||||
*cmd_type_len |= IGC_ADVTXD_DCMD_TSE;
|
||||
*olinfo_status |= IGC_TXD_POPTS_TXSM << 8;
|
||||
*olinfo_status |= paylen << IGC_ADVTXD_PAYLEN_SHIFT;
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Advanced Context Descriptor setup for VLAN, CSUM or TSO
|
||||
*
|
||||
**********************************************************************/
|
||||
static int
|
||||
igc_tx_ctx_setup(struct tx_ring *txr, if_pkt_info_t pi, uint32_t *cmd_type_len,
|
||||
uint32_t *olinfo_status)
|
||||
{
|
||||
struct igc_adv_tx_context_desc *TXD;
|
||||
uint32_t vlan_macip_lens, type_tucmd_mlhl;
|
||||
uint32_t mss_l4len_idx;
|
||||
mss_l4len_idx = vlan_macip_lens = type_tucmd_mlhl = 0;
|
||||
|
||||
/* First check if TSO is to be used */
|
||||
if (pi->ipi_csum_flags & CSUM_TSO)
|
||||
return (igc_tso_setup(txr, pi, cmd_type_len, olinfo_status));
|
||||
|
||||
/* Indicate the whole packet as payload when not doing TSO */
|
||||
*olinfo_status |= pi->ipi_len << IGC_ADVTXD_PAYLEN_SHIFT;
|
||||
|
||||
/* Now ready a context descriptor */
|
||||
TXD = (struct igc_adv_tx_context_desc *) &txr->tx_base[pi->ipi_pidx];
|
||||
|
||||
/*
|
||||
** In advanced descriptors the vlan tag must
|
||||
** be placed into the context descriptor. Hence
|
||||
** we need to make one even if not doing offloads.
|
||||
*/
|
||||
if (pi->ipi_mflags & M_VLANTAG) {
|
||||
vlan_macip_lens |= (pi->ipi_vtag << IGC_ADVTXD_VLAN_SHIFT);
|
||||
} else if ((pi->ipi_csum_flags & IGC_CSUM_OFFLOAD) == 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set the ether header length */
|
||||
vlan_macip_lens |= pi->ipi_ehdrlen << IGC_ADVTXD_MACLEN_SHIFT;
|
||||
|
||||
switch(pi->ipi_etype) {
|
||||
case ETHERTYPE_IP:
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV4;
|
||||
break;
|
||||
case ETHERTYPE_IPV6:
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV6;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vlan_macip_lens |= pi->ipi_ip_hlen;
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_DCMD_DEXT | IGC_ADVTXD_DTYP_CTXT;
|
||||
|
||||
switch (pi->ipi_ipproto) {
|
||||
case IPPROTO_TCP:
|
||||
if (pi->ipi_csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP)) {
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_L4T_TCP;
|
||||
*olinfo_status |= IGC_TXD_POPTS_TXSM << 8;
|
||||
}
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
if (pi->ipi_csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP)) {
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_L4T_UDP;
|
||||
*olinfo_status |= IGC_TXD_POPTS_TXSM << 8;
|
||||
}
|
||||
break;
|
||||
#ifndef __HAIKU__
|
||||
case IPPROTO_SCTP:
|
||||
if (pi->ipi_csum_flags & (CSUM_IP_SCTP | CSUM_IP6_SCTP)) {
|
||||
type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_L4T_SCTP;
|
||||
*olinfo_status |= IGC_TXD_POPTS_TXSM << 8;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now copy bits into descriptor */
|
||||
TXD->vlan_macip_lens = htole32(vlan_macip_lens);
|
||||
TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
|
||||
TXD->seqnum_seed = htole32(0);
|
||||
TXD->mss_l4len_idx = htole32(mss_l4len_idx);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
igc_isc_txd_encap(void *arg, if_pkt_info_t pi)
|
||||
{
|
||||
struct igc_adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
struct igc_tx_queue *que = &sc->tx_queues[pi->ipi_qsidx];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
int nsegs = pi->ipi_nsegs;
|
||||
bus_dma_segment_t *segs = pi->ipi_segs;
|
||||
union igc_adv_tx_desc *txd = NULL;
|
||||
int i, j, pidx_last;
|
||||
uint32_t olinfo_status, cmd_type_len, txd_flags;
|
||||
qidx_t ntxd;
|
||||
|
||||
pidx_last = olinfo_status = 0;
|
||||
/* Basic descriptor defines */
|
||||
cmd_type_len = (IGC_ADVTXD_DTYP_DATA |
|
||||
IGC_ADVTXD_DCMD_IFCS | IGC_ADVTXD_DCMD_DEXT);
|
||||
|
||||
if (pi->ipi_mflags & M_VLANTAG)
|
||||
cmd_type_len |= IGC_ADVTXD_DCMD_VLE;
|
||||
|
||||
i = pi->ipi_pidx;
|
||||
ntxd = scctx->isc_ntxd[0];
|
||||
txd_flags = pi->ipi_flags & IPI_TX_INTR ? IGC_ADVTXD_DCMD_RS : 0;
|
||||
/* Consume the first descriptor */
|
||||
i += igc_tx_ctx_setup(txr, pi, &cmd_type_len, &olinfo_status);
|
||||
if (i == scctx->isc_ntxd[0])
|
||||
i = 0;
|
||||
|
||||
for (j = 0; j < nsegs; j++) {
|
||||
bus_size_t seglen;
|
||||
bus_addr_t segaddr;
|
||||
|
||||
txd = (union igc_adv_tx_desc *)&txr->tx_base[i];
|
||||
seglen = segs[j].ds_len;
|
||||
segaddr = htole64(segs[j].ds_addr);
|
||||
|
||||
txd->read.buffer_addr = segaddr;
|
||||
txd->read.cmd_type_len = htole32(IGC_ADVTXD_DCMD_IFCS |
|
||||
cmd_type_len | seglen);
|
||||
txd->read.olinfo_status = htole32(olinfo_status);
|
||||
pidx_last = i;
|
||||
if (++i == scctx->isc_ntxd[0]) {
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
if (txd_flags) {
|
||||
txr->tx_rsq[txr->tx_rs_pidx] = pidx_last;
|
||||
txr->tx_rs_pidx = (txr->tx_rs_pidx+1) & (ntxd-1);
|
||||
MPASS(txr->tx_rs_pidx != txr->tx_rs_cidx);
|
||||
}
|
||||
|
||||
txd->read.cmd_type_len |= htole32(IGC_ADVTXD_DCMD_EOP | txd_flags);
|
||||
pi->ipi_new_pidx = i;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
igc_isc_txd_flush(void *arg, uint16_t txqid, qidx_t pidx)
|
||||
{
|
||||
struct igc_adapter *adapter = arg;
|
||||
struct igc_tx_queue *que = &adapter->tx_queues[txqid];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
|
||||
IGC_WRITE_REG(&adapter->hw, IGC_TDT(txr->me), pidx);
|
||||
}
|
||||
|
||||
static int
|
||||
igc_isc_txd_credits_update(void *arg, uint16_t txqid, bool clear)
|
||||
{
|
||||
struct igc_adapter *adapter = arg;
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct igc_tx_queue *que = &adapter->tx_queues[txqid];
|
||||
struct tx_ring *txr = &que->txr;
|
||||
|
||||
qidx_t processed = 0;
|
||||
int updated;
|
||||
qidx_t cur, prev, ntxd, rs_cidx;
|
||||
int32_t delta;
|
||||
uint8_t status;
|
||||
|
||||
rs_cidx = txr->tx_rs_cidx;
|
||||
if (rs_cidx == txr->tx_rs_pidx)
|
||||
return (0);
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
status = ((union igc_adv_tx_desc *)&txr->tx_base[cur])->wb.status;
|
||||
updated = !!(status & IGC_TXD_STAT_DD);
|
||||
|
||||
if (!updated)
|
||||
return (0);
|
||||
|
||||
/* If clear is false just let caller know that there
|
||||
* are descriptors to reclaim */
|
||||
if (!clear)
|
||||
return (1);
|
||||
|
||||
prev = txr->tx_cidx_processed;
|
||||
ntxd = scctx->isc_ntxd[0];
|
||||
do {
|
||||
MPASS(prev != cur);
|
||||
delta = (int32_t)cur - (int32_t)prev;
|
||||
if (delta < 0)
|
||||
delta += ntxd;
|
||||
MPASS(delta > 0);
|
||||
|
||||
processed += delta;
|
||||
prev = cur;
|
||||
rs_cidx = (rs_cidx + 1) & (ntxd-1);
|
||||
if (rs_cidx == txr->tx_rs_pidx)
|
||||
break;
|
||||
cur = txr->tx_rsq[rs_cidx];
|
||||
status = ((union igc_adv_tx_desc *)&txr->tx_base[cur])->wb.status;
|
||||
} while ((status & IGC_TXD_STAT_DD));
|
||||
|
||||
txr->tx_rs_cidx = rs_cidx;
|
||||
txr->tx_cidx_processed = prev;
|
||||
return (processed);
|
||||
}
|
||||
|
||||
static void
|
||||
igc_isc_rxd_refill(void *arg, if_rxd_update_t iru)
|
||||
{
|
||||
struct igc_adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
uint16_t rxqid = iru->iru_qsidx;
|
||||
struct igc_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
union igc_adv_rx_desc *rxd;
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
uint64_t *paddrs;
|
||||
uint32_t next_pidx, pidx;
|
||||
uint16_t count;
|
||||
int i;
|
||||
|
||||
paddrs = iru->iru_paddrs;
|
||||
pidx = iru->iru_pidx;
|
||||
count = iru->iru_count;
|
||||
|
||||
for (i = 0, next_pidx = pidx; i < count; i++) {
|
||||
rxd = (union igc_adv_rx_desc *)&rxr->rx_base[next_pidx];
|
||||
|
||||
rxd->read.pkt_addr = htole64(paddrs[i]);
|
||||
if (++next_pidx == scctx->isc_nrxd[0])
|
||||
next_pidx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
igc_isc_rxd_flush(void *arg, uint16_t rxqid, uint8_t flid __unused, qidx_t pidx)
|
||||
{
|
||||
struct igc_adapter *sc = arg;
|
||||
struct igc_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
|
||||
IGC_WRITE_REG(&sc->hw, IGC_RDT(rxr->me), pidx);
|
||||
}
|
||||
|
||||
static int
|
||||
igc_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget)
|
||||
{
|
||||
struct igc_adapter *sc = arg;
|
||||
if_softc_ctx_t scctx = sc->shared;
|
||||
struct igc_rx_queue *que = &sc->rx_queues[rxqid];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
union igc_adv_rx_desc *rxd;
|
||||
uint32_t staterr = 0;
|
||||
int cnt, i;
|
||||
|
||||
for (cnt = 0, i = idx; cnt < scctx->isc_nrxd[0] && cnt <= budget;) {
|
||||
rxd = (union igc_adv_rx_desc *)&rxr->rx_base[i];
|
||||
staterr = le32toh(rxd->wb.upper.status_error);
|
||||
|
||||
if ((staterr & IGC_RXD_STAT_DD) == 0)
|
||||
break;
|
||||
if (++i == scctx->isc_nrxd[0])
|
||||
i = 0;
|
||||
if (staterr & IGC_RXD_STAT_EOP)
|
||||
cnt++;
|
||||
}
|
||||
return (cnt);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* Routine sends data which has been dma'ed into host memory
|
||||
* to upper layer. Initialize ri structure.
|
||||
*
|
||||
* Returns 0 upon success, errno on failure
|
||||
***************************************************************/
|
||||
|
||||
static int
|
||||
igc_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri)
|
||||
{
|
||||
struct igc_adapter *adapter = arg;
|
||||
if_softc_ctx_t scctx = adapter->shared;
|
||||
struct igc_rx_queue *que = &adapter->rx_queues[ri->iri_qsidx];
|
||||
struct rx_ring *rxr = &que->rxr;
|
||||
union igc_adv_rx_desc *rxd;
|
||||
|
||||
uint16_t pkt_info, len, vtag;
|
||||
uint32_t ptype, staterr;
|
||||
int i, cidx;
|
||||
bool eop;
|
||||
|
||||
staterr = i = vtag = 0;
|
||||
cidx = ri->iri_cidx;
|
||||
|
||||
do {
|
||||
rxd = (union igc_adv_rx_desc *)&rxr->rx_base[cidx];
|
||||
staterr = le32toh(rxd->wb.upper.status_error);
|
||||
pkt_info = le16toh(rxd->wb.lower.lo_dword.hs_rss.pkt_info);
|
||||
|
||||
MPASS ((staterr & IGC_RXD_STAT_DD) != 0);
|
||||
|
||||
len = le16toh(rxd->wb.upper.length);
|
||||
ptype = le32toh(rxd->wb.lower.lo_dword.data) & IGC_PKTTYPE_MASK;
|
||||
|
||||
ri->iri_len += len;
|
||||
rxr->rx_bytes += ri->iri_len;
|
||||
|
||||
rxd->wb.upper.status_error = 0;
|
||||
eop = ((staterr & IGC_RXD_STAT_EOP) == IGC_RXD_STAT_EOP);
|
||||
|
||||
vtag = le16toh(rxd->wb.upper.vlan);
|
||||
|
||||
/* Make sure bad packets are discarded */
|
||||
if (eop && ((staterr & IGC_RXDEXT_STATERR_RXE) != 0)) {
|
||||
adapter->dropped_pkts++;
|
||||
++rxr->rx_discarded;
|
||||
return (EBADMSG);
|
||||
}
|
||||
ri->iri_frags[i].irf_flid = 0;
|
||||
ri->iri_frags[i].irf_idx = cidx;
|
||||
ri->iri_frags[i].irf_len = len;
|
||||
|
||||
if (++cidx == scctx->isc_nrxd[0])
|
||||
cidx = 0;
|
||||
#ifdef notyet
|
||||
if (rxr->hdr_split == true) {
|
||||
ri->iri_frags[i].irf_flid = 1;
|
||||
ri->iri_frags[i].irf_idx = cidx;
|
||||
if (++cidx == scctx->isc_nrxd[0])
|
||||
cidx = 0;
|
||||
}
|
||||
#endif
|
||||
i++;
|
||||
} while (!eop);
|
||||
|
||||
rxr->rx_packets++;
|
||||
|
||||
if ((scctx->isc_capenable & IFCAP_RXCSUM) != 0)
|
||||
igc_rx_checksum(staterr, ri, ptype);
|
||||
|
||||
if ((scctx->isc_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
|
||||
(staterr & IGC_RXD_STAT_VP) != 0) {
|
||||
ri->iri_vtag = vtag;
|
||||
ri->iri_flags |= M_VLANTAG;
|
||||
}
|
||||
|
||||
ri->iri_flowid =
|
||||
le32toh(rxd->wb.lower.hi_dword.rss);
|
||||
ri->iri_rsstype = igc_determine_rsstype(pkt_info);
|
||||
ri->iri_nfrags = i;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Verify that the hardware indicated that the checksum is valid.
|
||||
* Inform the stack about the status of checksum so that stack
|
||||
* doesn't spend time verifying the checksum.
|
||||
*
|
||||
*********************************************************************/
|
||||
static void
|
||||
igc_rx_checksum(uint32_t staterr, if_rxd_info_t ri, uint32_t ptype)
|
||||
{
|
||||
uint16_t status = (uint16_t)staterr;
|
||||
uint8_t errors = (uint8_t)(staterr >> 24);
|
||||
|
||||
if (__predict_false(status & IGC_RXD_STAT_IXSM))
|
||||
return;
|
||||
|
||||
/* If there is a layer 3 or 4 error we are done */
|
||||
if (__predict_false(errors & (IGC_RXD_ERR_IPE | IGC_RXD_ERR_TCPE)))
|
||||
return;
|
||||
|
||||
/* IP Checksum Good */
|
||||
if (status & IGC_RXD_STAT_IPCS)
|
||||
ri->iri_csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID);
|
||||
|
||||
/* Valid L4E checksum */
|
||||
if (__predict_true(status &
|
||||
(IGC_RXD_STAT_TCPCS | IGC_RXD_STAT_UDPCS))) {
|
||||
/* SCTP header present */
|
||||
if (__predict_false((ptype & IGC_RXDADV_PKTTYPE_ETQF) == 0 &&
|
||||
(ptype & IGC_RXDADV_PKTTYPE_SCTP) != 0)) {
|
||||
ri->iri_csum_flags |= CSUM_SCTP_VALID;
|
||||
} else {
|
||||
ri->iri_csum_flags |= CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
|
||||
ri->iri_csum_data = htons(0xffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
*
|
||||
* Parse the packet type to determine the appropriate hash
|
||||
*
|
||||
******************************************************************/
|
||||
static int
|
||||
igc_determine_rsstype(uint16_t pkt_info)
|
||||
{
|
||||
switch (pkt_info & IGC_RXDADV_RSSTYPE_MASK) {
|
||||
case IGC_RXDADV_RSSTYPE_IPV4_TCP:
|
||||
return M_HASHTYPE_RSS_TCP_IPV4;
|
||||
case IGC_RXDADV_RSSTYPE_IPV4:
|
||||
return M_HASHTYPE_RSS_IPV4;
|
||||
case IGC_RXDADV_RSSTYPE_IPV6_TCP:
|
||||
return M_HASHTYPE_RSS_TCP_IPV6;
|
||||
case IGC_RXDADV_RSSTYPE_IPV6_EX:
|
||||
return M_HASHTYPE_RSS_IPV6_EX;
|
||||
case IGC_RXDADV_RSSTYPE_IPV6:
|
||||
return M_HASHTYPE_RSS_IPV6;
|
||||
case IGC_RXDADV_RSSTYPE_IPV6_TCP_EX:
|
||||
return M_HASHTYPE_RSS_TCP_IPV6_EX;
|
||||
default:
|
||||
return M_HASHTYPE_OPAQUE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2021, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/bus.h>
|
||||
|
||||
|
||||
HAIKU_FBSD_DRIVER_GLUE(intel22x, igc, pci);
|
||||
HAIKU_DRIVER_REQUIREMENTS(0);
|
||||
NO_HAIKU_FBSD_MII_DRIVER();
|
||||
NO_HAIKU_CHECK_DISABLE_INTERRUPTS();
|
||||
NO_HAIKU_REENABLE_INTERRUPTS();
|
||||
Reference in New Issue
Block a user