#ifndef _RGE_H
#define _RGE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/strsun.h>
#include <sys/strsubr.h>
#include <sys/stat.h>
#include <sys/pci.h>
#include <sys/pci_cap.h>
#include <sys/note.h>
#include <sys/modctl.h>
#include <sys/kstat.h>
#include <sys/ethernet.h>
#include <sys/vlan.h>
#include <sys/errno.h>
#include <sys/dlpi.h>
#include <sys/devops.h>
#include <sys/debug.h>
#include <sys/conf.h>
#include <netinet/ip6.h>
#include <inet/common.h>
#include <inet/ip.h>
#include <inet/mi.h>
#include <inet/nd.h>
#include <sys/pattr.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/mac_provider.h>
#include <sys/mac_ether.h>
extern int secpolicy_net_config(const cred_t *, boolean_t);
#include <sys/netlb.h>
#include <sys/miiregs.h>
#include "rge_hw.h"
#define RGE_DRIVER_NAME "rge"
#define RGE_LOOP_NONE 0
#define RGE_LOOP_INTERNAL_PHY 1
#define RGE_LOOP_INTERNAL_MAC 2
#define RGE_IOC ((((('R' << 8) + 'G') << 8) + 'E') << 8)
#define RGE_MII_READ (RGE_IOC|1)
#define RGE_MII_WRITE (RGE_IOC|2)
struct rge_mii_rw {
uint32_t mii_reg;
uint32_t mii_data;
};
#define RGE_DIAG (RGE_IOC|10)
#define RGE_PEEK (RGE_IOC|11)
#define RGE_POKE (RGE_IOC|12)
#define RGE_PHY_RESET (RGE_IOC|13)
#define RGE_SOFT_RESET (RGE_IOC|14)
#define RGE_HARD_RESET (RGE_IOC|15)
typedef struct {
uint64_t pp_acc_size;
uint64_t pp_acc_space;
uint64_t pp_acc_offset;
uint64_t pp_acc_data;
} rge_peekpoke_t;
#define RGE_PP_SPACE_CFG 0
#define RGE_PP_SPACE_REG 1
#define RGE_PP_SPACE_MII 2
#define RGE_PP_SPACE_RGE 3
#define RGE_PP_SPACE_TXDESC 4
#define RGE_PP_SPACE_TXBUFF 5
#define RGE_PP_SPACE_RXDESC 6
#define RGE_PP_SPACE_RXBUFF 7
#define RGE_PP_SPACE_STATISTICS 8
#define RGE_HASH_POLY 0x04C11DB7
#define RGE_HASH_CRC 0xFFFFFFFFU
#define RGE_MCAST_BUF_SIZE 64
#define RGE_BUF_SLOTS 2048
#define RGE_RECV_COPY_SIZE 256
#define RGE_HEADROOM 6
#define RGE_CYCLIC_PERIOD (1000000000)
#define CHIP_RESET_LOOP 1000
#define PHY_RESET_LOOP 10
#define STATS_DUMP_LOOP 1000
#define RXBUFF_FREE_LOOP 1000
#define RGE_RX_INT_TIME 128
#define RGE_RX_INT_PKTS 8
typedef struct {
int ndp_info;
int ndp_min;
int ndp_max;
int ndp_val;
char *ndp_name;
} nd_param_t;
enum {
PARAM_AUTONEG_CAP = 0,
PARAM_PAUSE_CAP,
PARAM_ASYM_PAUSE_CAP,
PARAM_1000FDX_CAP,
PARAM_1000HDX_CAP,
PARAM_100T4_CAP,
PARAM_100FDX_CAP,
PARAM_100HDX_CAP,
PARAM_10FDX_CAP,
PARAM_10HDX_CAP,
PARAM_ADV_AUTONEG_CAP,
PARAM_ADV_PAUSE_CAP,
PARAM_ADV_ASYM_PAUSE_CAP,
PARAM_ADV_1000FDX_CAP,
PARAM_ADV_1000HDX_CAP,
PARAM_ADV_100T4_CAP,
PARAM_ADV_100FDX_CAP,
PARAM_ADV_100HDX_CAP,
PARAM_ADV_10FDX_CAP,
PARAM_ADV_10HDX_CAP,
PARAM_LINK_STATUS,
PARAM_LINK_SPEED,
PARAM_LINK_DUPLEX,
PARAM_LOOP_MODE,
PARAM_COUNT
};
enum rge_chip_state {
RGE_CHIP_FAULT = -2,
RGE_CHIP_ERROR,
RGE_CHIP_INITIAL,
RGE_CHIP_RESET,
RGE_CHIP_STOPPED,
RGE_CHIP_RUNNING
};
enum rge_mac_state {
RGE_MAC_ATTACH = 0,
RGE_MAC_STOPPED,
RGE_MAC_STARTED,
RGE_MAC_UNATTACH
};
enum rge_sync_op {
RGE_OP_NULL,
RGE_GET_MAC,
RGE_SET_MAC,
RGE_SET_MUL,
RGE_SET_PROMISC
};
enum ioc_reply {
IOC_INVAL = -1,
IOC_DONE,
IOC_ACK,
IOC_REPLY,
IOC_RESTART_ACK,
IOC_RESTART_REPLY
};
enum {
RGE_KSTAT_DRIVER = 0,
RGE_KSTAT_COUNT
};
typedef uintptr_t rge_regno_t;
#define RGE_REGNO_NONE (~(uintptr_t)0u)
typedef struct {
ddi_acc_handle_t acc_hdl;
void *mem_va;
uint32_t nslots;
uint32_t size;
size_t alength;
ddi_dma_handle_t dma_hdl;
offset_t offset;
ddi_dma_cookie_t cookie;
uint32_t ncookies;
uint32_t token;
} dma_area_t;
typedef struct {
caddr_t private;
dma_area_t pbuf;
frtn_t rx_recycle;
mblk_t *mp;
} dma_buf_t;
typedef struct sw_rbd {
dma_buf_t *rx_buf;
uint8_t flags;
} sw_rbd_t;
typedef struct sw_sbd {
dma_area_t desc;
dma_area_t pbuf;
} sw_sbd_t;
#define HW_RBD_INIT(rbd, slot) { \
(rbd)->vlan_tag = 0; \
if ((slot) == (RGE_RECV_SLOTS -1)) { \
(rbd)->flags_len |= \
RGE_BSWAP_32(BD_FLAG_EOR | BD_FLAG_HW_OWN); \
} else { \
(rbd)->flags_len |= RGE_BSWAP_32(BD_FLAG_HW_OWN); \
} \
}
#define HW_SBD_SET(sbd, slot) { \
if ((slot) == (RGE_SEND_SLOTS -1)) { \
(sbd)->flags_len |= \
RGE_BSWAP_32(BD_FLAG_EOR | SBD_FLAG_TX_PKT); \
} else { \
(sbd)->flags_len |= RGE_BSWAP_32(SBD_FLAG_TX_PKT); \
} \
}
typedef struct {
uint16_t command;
uint16_t vendor;
uint16_t device;
uint16_t subven;
uint16_t subdev;
uint8_t revision;
uint8_t clsize;
uint8_t latency;
boolean_t is_pcie;
boolean_t enable_mac_first;
uint32_t mac_ver;
uint32_t phy_ver;
uint32_t rxconfig;
uint32_t txconfig;
} chip_id_t;
typedef struct rge_stats {
uint64_t rpackets;
uint64_t rbytes;
uint64_t opackets;
uint64_t obytes;
uint32_t overflow;
uint32_t defer;
uint32_t crc_err;
uint32_t in_short;
uint32_t no_rcvbuf;
uint32_t intr;
uint16_t chip_reset;
uint16_t phy_reset;
boolean_t tx_pre_ismax;
boolean_t tx_cur_ismax;
} rge_stats_t;
typedef struct rge {
dev_info_t *devinfo;
mac_handle_t mh;
ddi_acc_handle_t cfg_handle;
ddi_acc_handle_t io_handle;
caddr_t io_regs;
ddi_periodic_t periodic_id;
ddi_softint_handle_t resched_hdl;
ddi_softint_handle_t factotum_hdl;
uint_t soft_pri;
ddi_intr_handle_t *htable;
int intr_type;
int intr_rqst;
int intr_cnt;
uint_t intr_pri;
int intr_cap;
boolean_t msi_enable;
uint32_t ethmax_size;
uint32_t default_mtu;
uint32_t rxbuf_size;
uint32_t txbuf_size;
uint32_t chip_flags;
uint32_t head_room;
char ifname[8];
int32_t instance;
uint32_t progress;
uint32_t debug;
chip_id_t chipid;
dma_area_t dma_area_rxdesc;
dma_area_t dma_area_txdesc;
dma_area_t dma_area_stats;
uint8_t netaddr[ETHERADDRL];
uint16_t int_mask;
char mcast_refs[RGE_MCAST_BUF_SIZE];
uint8_t mcast_hash[RGE_MCAST_NUM];
boolean_t promisc;
rge_bd_t *rx_ring;
dma_area_t rx_desc;
boolean_t rx_bcopy;
uint32_t rx_next;
sw_rbd_t *sw_rbds;
sw_rbd_t *free_srbds;
uint32_t rf_next;
uint32_t rc_next;
uint32_t rx_free;
rge_bd_t *tx_ring;
dma_area_t tx_desc;
uint32_t tx_free;
uint32_t tx_next;
uint32_t tc_next;
uint32_t tx_flow;
uint32_t tc_tail;
sw_sbd_t *sw_sbds;
kmutex_t genlock[1];
krwlock_t errlock[1];
kmutex_t tx_lock[1];
kmutex_t tc_lock[1];
kmutex_t rx_lock[1];
kmutex_t rc_lock[1];
uint32_t watchdog;
boolean_t resched_needed;
uint32_t factotum_flag;
rge_regno_t phy_mii_addr;
uint16_t link_down_count;
caddr_t nd_data_p;
nd_param_t nd_params[PARAM_COUNT];
kstat_t *rge_kstats[RGE_KSTAT_COUNT];
rge_hw_stats_t *hw_stats;
rge_stats_t stats;
enum rge_mac_state rge_mac_state;
enum rge_chip_state rge_chip_state;
boolean_t suspended;
#define TX_COALESC max(RGE_BUF_SLOTS/32LL, 8)
#define RX_COALESC 8LL
#define CLK_TICK 100
clock_t curr_tick;
clock_t tick_delta;
uint64_t last_opackets;
uint64_t last_rpackets;
uint32_t rx_fifo_ovf;
} rge_t;
#define PROGRESS_CFG 0x0001
#define PROGRESS_REGS 0x0002
#define PROGRESS_RESCHED 0x0010
#define PROGRESS_FACTOTUM 0x0020
#define PROGRESS_INTR 0X0040
#define PROGRESS_INIT 0x0080
#define PROGRESS_PHY 0x0100
#define PROGRESS_NDD 0x1000
#define PROGRESS_KSTATS 0x2000
#define PROGRESS_READY 0x8000
#define CHIP_FLAG_FORCE_BCOPY 0x10000000
#define param_adv_autoneg nd_params[PARAM_ADV_AUTONEG_CAP].ndp_val
#define param_adv_pause nd_params[PARAM_ADV_PAUSE_CAP].ndp_val
#define param_adv_asym_pause nd_params[PARAM_ADV_ASYM_PAUSE_CAP].ndp_val
#define param_adv_1000fdx nd_params[PARAM_ADV_1000FDX_CAP].ndp_val
#define param_adv_1000hdx nd_params[PARAM_ADV_1000HDX_CAP].ndp_val
#define param_adv_100fdx nd_params[PARAM_ADV_100FDX_CAP].ndp_val
#define param_adv_100hdx nd_params[PARAM_ADV_100HDX_CAP].ndp_val
#define param_adv_10fdx nd_params[PARAM_ADV_10FDX_CAP].ndp_val
#define param_adv_10hdx nd_params[PARAM_ADV_10HDX_CAP].ndp_val
#define param_link_up nd_params[PARAM_LINK_STATUS].ndp_val
#define param_link_speed nd_params[PARAM_LINK_SPEED].ndp_val
#define param_link_duplex nd_params[PARAM_LINK_DUPLEX].ndp_val
#define param_loop_mode nd_params[PARAM_LOOP_MODE].ndp_val
#define DMA_SYNC(area, flag) ((void) ddi_dma_sync((area).dma_hdl, \
(area).offset, (area).alength, (flag)))
#define DMA_VPTR(area) ((area).mem_va)
#define DMA_ZERO(area) bzero(DMA_VPTR(area), (area).alength)
#define NEXT(index, limit) ((index)+1 < (limit) ? (index)+1 : 0);
#define LAST(index, limit) ((index) ? (index)-1 : (limit - 1));
#define RGE_PROP_EXISTS(d, n) ddi_prop_exists(DDI_DEV_T_ANY, (d), \
DDI_PROP_DONTPASS, (n))
#define RGE_PROP_GET_INT(d, n) ddi_prop_get_int(DDI_DEV_T_ANY, (d), \
DDI_PROP_DONTPASS, (n), -1)
#ifdef _BIG_ENDIAN
#define RGE_BSWAP_16(x) ((((x) & 0xff00) >> 8) | \
(((x) & 0x00ff) << 8))
#define RGE_BSWAP_32(x) ((((x) & 0xff000000) >> 24) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x000000ff) << 24))
#define RGE_BSWAP_64(x) (RGE_BSWAP_32((x) >> 32) | \
(RGE_BSWAP_32(x) << 32))
#else
#define RGE_BSWAP_16(x) (x)
#define RGE_BSWAP_32(x) (x)
#define RGE_BSWAP_64(x) (x)
#endif
#define BIS(w, b) (((w) & (b)) ? B_TRUE : B_FALSE)
#define BIC(w, b) (((w) & (b)) ? B_FALSE : B_TRUE)
#define UPORDOWN(x) ((x) ? "up" : "down")
#define RGE_DBG_STOP 0x00000001
#define RGE_DBG_TRACE 0x00000002
#define RGE_DBG_REGS 0x00000010
#define RGE_DBG_MII 0x00000020
#define RGE_DBG_SEEPROM 0x00000040
#define RGE_DBG_CHIP 0x00000080
#define RGE_DBG_RECV 0x00000100
#define RGE_DBG_SEND 0x00000200
#define RGE_DBG_INT 0x00001000
#define RGE_DBG_FACT 0x00002000
#define RGE_DBG_PHY 0x00010000
#define RGE_DBG_SERDES 0x00020000
#define RGE_DBG_PHYS 0x00040000
#define RGE_DBG_LINK 0x00080000
#define RGE_DBG_INIT 0x00100000
#define RGE_DBG_NEMO 0x00200000
#define RGE_DBG_ADDR 0x00400000
#define RGE_DBG_STATS 0x00800000
#define RGE_DBG_IOCTL 0x01000000
#define RGE_DBG_LOOP 0x02000000
#define RGE_DBG_PPIO 0x04000000
#define RGE_DBG_BADIOC 0x08000000
#define RGE_DBG_MCTL 0x10000000
#define RGE_DBG_NDD 0x20000000
#ifdef DEBUG
#define RGE_DEBUGGING 1
#else
#define RGE_DEBUGGING 0
#endif
#if RGE_DEBUGGING
#define RGE_DDB(command) do { \
{ command; } \
_NOTE(CONSTANTCONDITION) \
} while (0)
#else
#define RGE_DDB(command) do { \
{ _NOTE(EMPTY); } \
_NOTE(CONSTANTCONDITION) \
} while (0)
#endif
#define RGE_XDB(b, w, f, args) RGE_DDB(if ((b) & (w)) f args)
#define RGE_GDB(b, args) RGE_XDB(b, rge_debug, (*rge_gdb()), args)
#define RGE_LDB(b, args) RGE_XDB(b, rgep->debug, (*rge_db(rgep)), args)
#define RGE_CDB(f, args) RGE_XDB(RGE_DBG, rgep->debug, f, args)
#define RGE_TRC RGE_DBG_TRACE
#define RGE_GTRACE(args) RGE_GDB(RGE_TRC, args)
#define RGE_GDEBUG(args) RGE_GDB(RGE_DBG, args)
#define RGE_TRACE(args) RGE_LDB(RGE_TRC, args)
#define RGE_DEBUG(args) RGE_LDB(RGE_DBG, args)
#define RGE_BRKPT(rgep, s) RGE_DDB(rge_dbg_enter(rgep, s))
#define RGE_MARK(rgep) RGE_DDB(rge_led_mark(rgep))
#define RGE_PCICHK(rgep) RGE_DDB(rge_pci_check(rgep))
#define RGE_PKTDUMP(args) RGE_DDB(rge_pkt_dump args)
#define RGE_REPORT(args) RGE_DDB(rge_log args)
uint16_t rge_mii_get16(rge_t *rgep, uintptr_t mii);
void rge_mii_put16(rge_t *rgep, uintptr_t mii, uint16_t data);
void rge_chip_cfg_init(rge_t *rgep, chip_id_t *cidp);
void rge_chip_ident(rge_t *rgep);
int rge_chip_reset(rge_t *rgep);
void rge_chip_init(rge_t *rgep);
void rge_chip_start(rge_t *rgep);
void rge_chip_stop(rge_t *rgep, boolean_t fault);
void rge_chip_sync(rge_t *rgep, enum rge_sync_op todo);
void rge_chip_blank(void *arg, time_t ticks, uint_t count, int flag);
void rge_tx_trigger(rge_t *rgep);
void rge_hw_stats_dump(rge_t *rgep);
uint_t rge_intr(caddr_t arg1, caddr_t arg2);
uint_t rge_chip_factotum(caddr_t arg1, caddr_t arg2);
void rge_chip_cyclic(void *arg);
enum ioc_reply rge_chip_ioctl(rge_t *rgep, queue_t *wq, mblk_t *mp,
struct iocblk *iocp);
boolean_t rge_phy_reset(rge_t *rgep);
void rge_phy_init(rge_t *rgep);
void rge_phy_update(rge_t *rgep);
void rge_init_kstats(rge_t *rgep, int instance);
void rge_fini_kstats(rge_t *rgep);
int rge_m_stat(void *arg, uint_t stat, uint64_t *val);
#if RGE_DEBUGGING
void (*rge_db(rge_t *rgep))(const char *fmt, ...);
void (*rge_gdb(void))(const char *fmt, ...);
void rge_pkt_dump(rge_t *rgep, rge_bd_t *hbp, sw_rbd_t *sdp, const char *msg);
void rge_dbg_enter(rge_t *rgep, const char *msg);
#endif
void rge_problem(rge_t *rgep, const char *fmt, ...);
void rge_notice(rge_t *rgep, const char *fmt, ...);
void rge_log(rge_t *rgep, const char *fmt, ...);
void rge_error(rge_t *rgep, const char *fmt, ...);
extern kmutex_t rge_log_mutex[1];
extern uint32_t rge_debug;
void rge_restart(rge_t *rgep);
int rge_nd_init(rge_t *rgep);
enum ioc_reply rge_nd_ioctl(rge_t *rgep, queue_t *wq, mblk_t *mp,
struct iocblk *iocp);
void rge_nd_cleanup(rge_t *rgep);
void rge_rx_recycle(caddr_t arg);
void rge_receive(rge_t *rgep);
void rge_send_recycle(rge_t *rgep);
mblk_t *rge_m_tx(void *arg, mblk_t *mp);
uint_t rge_reschedule(caddr_t arg1, caddr_t arg2);
#ifdef __cplusplus
}
#endif
#endif