/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Frank van der Linden.
*
* 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#ifndef ELXL_H
#define ELXL_H
/*
* This file defines the registers specific to the EtherLink XL family
* of NICs.
*/
#define REG_CMD_STAT 0x0e /* Write command, read status */
#define CMD_GLOBAL_RESET 0x0000
#define CMD_SELECT_WINDOW 0x0800
#define CMD_BNC_ENABLE 0x1000 /* enable 10BASE2 DC-DC converter */
#define CMD_RX_DISABLE 0x1800
#define CMD_RX_ENABLE 0x2000
#define CMD_RX_RESET 0x2800
#define CMD_UP_STALL 0x3000
#define CMD_UP_UNSTALL 0x3001
#define CMD_DN_STALL 0x3002
#define CMD_DN_UNSTALL 0x3003
#define CMD_TX_ENABLE 0x4800
#define CMD_TX_DISABLE 0x5000
#define CMD_TX_RESET 0x5800
#define CMD_INT_REQ 0x6000
#define CMD_INT_ACK 0x6800
#define CMD_INT_ENABLE 0x7000
#define CMD_IND_ENABLE 0x7800
#define CMD_SET_FILTER 0x8000
#define CMD_SET_RXEARLY 0x8800
#define CMD_SET_TXSTART 0x9800
#define CMD_STATS_ENABLE 0xa800
#define CMD_STATS_DISABLE 0xb000
#define CMD_BNC_DISABLE 0xb800 /* disable 10BASE2 DC-DC converter */
#define CMD_SET_TXRECLAIM 0xc000
#define CMD_CLEAR_HASHBIT 0xc800
#define CMD_SET_HASHBIT 0xcc00
/*
* Defines for the interrupt status register
*/
#define INT_LATCH 0x0001
#define INT_HOST_ERROR 0x0002
#define INT_TX_COMPLETE 0x0004
#define INT_RX_COMPLETE 0x0010
#define INT_RX_EARLY 0x0020
#define INT_REQUESTED 0x0040
#define INT_STATS 0x0080
#define INT_LINK 0x0100 /* NB: most NICs don't implement it! */
#define INT_DN_COMPLETE 0x0200
#define INT_UP_COMPLETE 0x0400
#define STAT_CMD_IN_PROGRESS 0x1000
#define INT_WATCHED \
(INT_HOST_ERROR | INT_STATS | INT_DN_COMPLETE | INT_UP_COMPLETE)
/*
* Flat address space registers (outside the windows)
*/
#define REG_TXPKTID 0x18 /* 90xB only */
#define REG_TIMER 0x1a
#define REG_TXSTATUS 0x1b
#define TXSTATUS_RECLAIM_ERR 0x02
#define TXSTATUS_STATUS_OFLOW 0x04 /* bad news! */
#define TXSTATUS_MAXCOLLISIONS 0x08
#define TXSTATUS_UNDERRUN 0x10
#define TXSTATUS_JABBER 0x20
#define TXSTATUS_INT_REQ 0x40
#define TXSTATUS_COMPLETE 0x80
#define TXSTATUS_ERRS 0x32
#define REG_INTSTATUSAUTO 0x1e
#define REG_DMACTRL 0x20
#define DMACTRL_DNCMPLREQ 0x00000002
#define DMACTRL_DNSTALLED 0x00000004
#define DMACTRL_UPCOMPLETE 0x00000008
#define DMACTRL_DNCOMPLETE 0x00000010
#define DMACTRL_UPRXEAREN 0x00000020
#define DMACTRL_ARNCNTDN 0x00000040
#define DMACTRL_DNINPROG 0x00000080
#define DMACTRL_CNTSPEED 0x00000100
#define DMACTRL_CNTDNMODE 0x00000200
#define DMACTRL_ALTSEQDIS 0x00010000
#define DMACTRL_DEFEATMWI 0x00100000
#define DMACTRL_DEFEATMRL 0x00200000
#define DMACTRL_UPOVERDIS 0x00400000
#define DMACTRL_TARGABORT 0x40000000
#define DMACTRL_MSTRABORT 0x80000000
#define REG_DNLISTPTR 0x24
#define REG_DNBURSTTHRESH 0x2a /* 90xB only */
#define REG_DNPRIOTHRESH 0x2c /* 90xB only */
#define REG_DNPOLL 0x2d /* 90xB only */
#define REG_TXFREETHRESH 0x2f /* 90x only */
#define REG_UPPKTSTATUS 0x30
#define REG_FREETIMER 0x34
#define REG_COUNTDOWN 0x36
#define REG_UPLISTPTR 0x38
#define REG_UPPRIOTHRESH 0x3c /* 90xB only */
#define REG_UPPOLL 0x3d /* 90xB only */
#define REG_UPBURSTTHRESH 0x3e /* 90xB only */
#define REG_REALTIMECNT 0x40 /* 90xB only */
#define REG_DNMAXBURST 0x78 /* 90xB only */
#define REG_UPMAXBURST 0x7a /* 90xB only */
/*
* Window 0. Eeprom access.
*/
#define W0_MFG_ID 0x00
#define W0_EE_CMD 0x0a
#define EE_CMD_ADDR 0x001f
#define EE_CMD_WRITE_EN 0x0000
#define EE_CMD_READ 0x0080
#define EE_CMD_READ8 0x0200
#define EE_CMD_BUSY 0x8000
#define W0_EE_DATA 0x0c
/*
* Window 2.
*/
#define W2_STATION_ADDRESS 0x00
#define W2_STATION_MASK 0x06
#define W2_RESET_OPTIONS 0x0c /* Reset options (90xB only) */
#define W2_RESET_OPT_LEDPOLAR 0x0010 /* invert LED polarity */
#define W2_RESET_OPT_PHYPOWER 0x4000 /* turn on PHY power */
/*
* Window 3.
*/
#define W3_INTERNAL_CONFIG 0x00 /* 32 bits */
#define W3_MAX_PKT_SIZE 0x04 /* 90xB only */
#define W3_MAC_CONTROL 0x06
#define MAC_CONTROL_FDX 0x0020
#define MAC_CONTROL_ALLOW_LARGE 0x0040
#define MAC_CONTROL_FLOW_EN 0x0100 /* 90xB only */
#define MAC_CONTROL_VLT_EN 0x0200 /* 90xB only */
/*
* This is reset options for the other cards, media options for
* the 90xB NICs. Reset options are in a separate register for
* the 90xB.
*
* Note that these bit values are also the same as the
* W3_RESET_OPTIONS media selection bits on 90x NICs, which
* conviently occupies the same register, and pretty much is
* the same thing. There are some differences in the upper bits,
* but we don't care about those.
*/
#define W3_MEDIAOPT 0x08
#define MEDIAOPT_100T4 0x0001
#define MEDIAOPT_100TX 0x0002
#define MEDIAOPT_100FX 0x0004
#define MEDIAOPT_10T 0x0008
#define MEDIAOPT_BNC 0x0010
#define MEDIAOPT_AUI 0x0020
#define MEDIAOPT_MII 0x0040
#define MEDIAOPT_10FL 0x0080
#define MEDIAOPT_MASK 0x00ff /* excludes 10BASEFL */
/*
* Window 4 registers.
*/
#define W4_MEDIASTAT 0xa
#define MEDIASTAT_SQE_EN 0x0008
#define MEDIASTAT_JABGUARD_EN 0x0040
#define MEDIASTAT_LINKBEAT_EN 0x0080
#define MEDIASTAT_LINKDETECT 0x0800
#define MEDIASTAT_AUI_DIS 0x8000
/*
* Window 4, offset 8 is defined for MII/PHY access for EtherLink XL
* cards.
*/
#define W4_PHYSMGMT 0x08
#define PHYSMGMT_CLK 0x0001
#define PHYSMGMT_DATA 0x0002
#define PHYSMGMT_DIR 0x0004
/*
* Counter in window 4 for packets with a bad start-of-stream delimiter/
*/
#define W4_BADSSD 0x0c
/*
* Upper bits of 20-bit byte counters.
*/
#define W4_UBYTESOK 0x0d
/*
* W6 registers, used for statistics
*/
#define W6_TX_BYTES 0x0c
#define W6_RX_BYTES 0x0a
#define W6_UPPER_FRAMES 0x09
#define W6_DEFER 0x08
#define W6_RX_FRAMES 0x07
#define W6_TX_FRAMES 0x06
#define W6_RX_OVERRUNS 0x05
#define W6_TX_LATE_COL 0x04
#define W6_SINGLE_COL 0x03
#define W6_MULT_COL 0x02
#define W6_SQE_ERRORS 0x01
#define W6_NO_CARRIER 0x00
/*
* Receive filter bits for use with CMD_SET_FILTER.
*/
#define FILTER_UNICAST 0x01
#define FILTER_ALLMULTI 0x02
#define FILTER_ALLBCAST 0x04
#define FILTER_PROMISC 0x08
#define FILTER_MULTIHASH 0x10 /* only on 90xB */
/*
* Window 7 registers. These are different for 90x and 90xB than
* for the EtherLink III / Fast EtherLink cards.
*/
#define W7_VLANMASK 0x00 /* 90xB only */
#define W7_VLANTYPE 0x04 /* 90xB only */
#define W7_TIMER 0x0a /* 90x only */
#define W7_TX_STATUS 0x0b /* 90x only */
#define W7_POWEREVENT 0x0c /* 90xB only */
#define W7_INTSTATUS 0x0e
/*
* The Internal Config register is different on 90xB cards. The
* different masks / shifts are defined here.
*/
/*
* Lower 16 bits.
*/
#define CONFIG_TXLARGE 0x4000
#define CONFIG_TXLARGE_SHIFT 14
#define CONFIG_RXLARGE 0x8000
#define CONFIG_RXLARGE_SHIFT 15
/*
* Upper 16 bits.
*/
#define XCVR_SEL_10T 0x00000000U
#define XCVR_SEL_AUI 0x00100000U
#define XCVR_SEL_BNC 0x00300000U
#define XCVR_SEL_100TX 0x00400000U /* 3com says don't use this! */
#define XCVR_SEL_100FX 0x00500000U
#define XCVR_SEL_MII 0x00600000U
#define XCVR_SEL_AUTO 0x00800000U
#define XCVR_SEL_MASK 0x00f00000U
#define RAM_PARTITION_5_3 0x00000000U
#define RAM_PARTITION_3_1 0x00010000U
#define RAM_PARTITION_1_1 0x00020000U
#define RAM_PARTITION_3_5 0x00030000U
#define RAM_PARTITION_MASK 0x00030000U
#define CONFIG_AUTOSEL 0x0100
#define CONFIG_AUTOSEL_SHIFT 8
#define CONFIG_DISABLEROM 0x0200
#define CONFIG_DISABLEROM_SHIFT 9
/*
* ID of internal PHY.
*/
#define INTPHY_ID 24
/*
* Fragment header as laid out in memory for DMA access.
*/
#define EX_FR_LENMASK 0x00001fff /* mask for length in fr_len field */
#define EX_FR_LAST 0x80000000 /* indicates last fragment */
/*
* 3Com NICs have separate structures for packet upload (receive) and
* download (transmit) descriptors. However, the structures for the
* "legacy" transmit format are nearly identical except for the fact
* that the third field is named differently and the bit fields are
* different. To maximize code reuse, we use a single type to cover
* both uses. Note that for receive we can arrange these in a loop,
* but not for transmit. Note also that for simplicity, we only use
* the "type 0" legacy DPD format -- the features offered by the newer
* type 1 format are not something we need.
*/
typedef struct ex_pd {
uint32_t pd_link;
uint32_t pd_shared;
uint32_t pd_addr;
uint32_t pd_len;
} ex_pd_t;
#define pd_fsh pd_shared
#define pd_status pd_shared
/*
* Type 0 Download Packet Descriptor (DPD). We don't use the other
* type, since it isn't supported by older 90x ASICs.
*/
struct ex_dpd {
uint32_t dpd_nextptr; /* prt to next fragheader */
uint32_t dpd_fsh; /* frame start header */
uint32_t dpd_addr;
uint32_t dpd_len;
};
struct ex_upd {
uint32_t upd_nextptr;
uint32_t upd_pktstatus;
uint32_t upd_addr; /* phys addr of frag */
uint32_t upd_len; /* length of frag */
};
#define DPD_DMADDR(s, t) \
((s)->sc_dpddma + ((char *)((t)->tx_dpd) - (char *)((s)->sc_dpd)))
/*
* Frame Start Header bitfields.
*/
#define EX_DPD_DNIND 0x80000000 /* intr on download done */
#define EX_DPD_TXIND 0x00008000 /* intr on tx done */
#define EX_DPD_NOCRC 0x00002000 /* no CRC append */
/*
* Lower 12 bits are the tx length for the 90x family. The 90xB
* assumes that the tx length is the sum of all frame lengths,
* and uses the bits as below. It also defines some more bits in
* the upper part.
*/
#define EX_DPD_EMPTY 0x20000000 /* no data in this DPD */
#define EX_DPD_UPDEFEAT 0x10000000 /* don't round tx lengths up */
#define EX_DPD_UDPCKSUM 0x08000000 /* do hardware UDP checksum */
#define EX_DPD_TCPCKSUM 0x04000000 /* do hardware TCP checksum */
#define EX_DPD_IPCKSUM 0x02000000 /* do hardware IP checksum */
#define EX_DPD_DNCMPLT 0x01000000 /* packet has been downloaded */
#define EX_DPD_IDMASK 0x000003fc /* mask for packet id */
#define EX_DPD_IDSHIFT 2
#define EX_DPD_RNDMASK 0x00000003 /* mask for rounding */
/* 0 -> dword, 2 -> word, 1,3 -> none */
/*
* upd_pktstatus bitfields.
* The *CKSUMERR fields are only valid if the matching *CHECKED field
* is set.
*/
#define EX_UPD_PKTLENMASK 0x00001fff /* 12:0 -> packet length */
#define EX_UPD_ERROR 0x00004000 /* rcv error */
#define EX_UPD_COMPLETE 0x00008000 /* rcv complete */
#define EX_UPD_OVERRUN 0x00010000 /* rcv overrun */
#define EX_UPD_RUNT 0x00020000 /* pkt < 60 bytes */
#define EX_UPD_ALIGNERR 0x00040000 /* alignment error */
#define EX_UPD_CRCERR 0x00080000 /* CRC error */
#define EX_UPD_OVERSIZED 0x00100000 /* oversize frame */
#define EX_UPD_DRIBBLEBITS 0x00800000 /* pkt had dribble bits */
#define EX_UPD_OVERFLOW 0x01000000 /* insufficient space for pkt */
#define EX_UPD_IPCKSUMERR 0x02000000 /* IP cksum error (90xB) */
#define EX_UPD_TCPCKSUMERR 0x04000000 /* TCP cksum error (90xB) */
#define EX_UPD_UDPCKSUMERR 0x08000000 /* UDP cksum error (90xB) */
#define EX_UPD_IPCHECKED 0x20000000 /* IP cksum done */
#define EX_UPD_TCPCHECKED 0x40000000 /* TCP cksum done */
#define EX_UPD_UDPCHECKED 0x80000000 /* UDP cksum done */
#define EX_UPD_ERR 0x001f4000 /* Errors we check for */
#define EX_UPD_ERR_VLAN 0x000f0000 /* same for 802.1q */
#define EX_UPD_CKSUMERR 0x0e000000 /* any IP checksum error */
/*
* EEPROM offsets. These are 16-bit word addresses. There are a lot of
* other things in here, but we only care about the OEM address.
*/
#define EE_3COM_ADDR_0 0x00
#define EE_3COM_ADDR_1 0x01
#define EE_3COM_ADDR_2 0x02
#define EE_OEM_ADDR_0 0x0a
#define EE_OEM_ADDR_1 0x0b
#define EE_OEM_ADDR_2 0x0c
#define EE_CAPABILITIES 0x10
#define EX_NTX 256
#define EX_NRX 128
#define EX_BUFSZ 1536
typedef struct ex_desc {
struct ex_desc *ed_next;
struct ex_desc *ed_prev;
ddi_dma_handle_t ed_dmah;
ddi_acc_handle_t ed_acch;
caddr_t ed_buf;
uint32_t ed_bufaddr;
uint32_t ed_descaddr;
uint32_t ed_off; /* offset of pd */
ex_pd_t *ed_pd;
} ex_desc_t;
typedef struct ex_ring {
int r_count;
int r_avail;
ddi_dma_handle_t r_dmah;
ddi_acc_handle_t r_acch;
uint32_t r_paddr;
ex_pd_t *r_pd;
ex_desc_t *r_desc;
ex_desc_t *r_head;
ex_desc_t *r_tail;
} ex_ring_t;
/*
* Higher level linked list of upload packet descriptors.
*/
struct ex_rxdesc {
ddi_dma_handle_t rx_dmah;
ddi_acc_handle_t rx_acch;
caddr_t rx_buf;
uint32_t rx_paddr;
struct ex_upd *rx_upd;
};
/*
* Ethernet software status per interface.
*/
typedef struct ex_softc {
dev_info_t *ex_dip;
mac_handle_t ex_mach;
mii_handle_t ex_miih;
ddi_periodic_t ex_linkcheck;
ddi_acc_handle_t ex_pcih;
ddi_acc_handle_t ex_regsh;
caddr_t ex_regsva;
kmutex_t ex_txlock;
kmutex_t ex_intrlock;
ddi_intr_handle_t ex_intrh;
uint8_t ex_curraddr[6];
uint8_t ex_factaddr[6];
boolean_t ex_promisc;
unsigned ex_mccount;
boolean_t ex_running;
boolean_t ex_suspended;
ex_ring_t ex_rxring;
ex_ring_t ex_txring;
uint32_t ex_xcvr;
uint32_t ex_speed;
link_duplex_t ex_duplex;
boolean_t ex_fdx;
link_state_t ex_link;
boolean_t ex_mii_active;
uint32_t ex_mediaopt;
char ex_medias[128];
uint16_t ex_capab;
/*
* Kstats.
*/
uint64_t ex_ipackets;
uint64_t ex_opackets;
uint64_t ex_ibytes;
uint64_t ex_obytes;
uint64_t ex_brdcstrcv;
uint64_t ex_multircv;
uint64_t ex_brdcstxmt;
uint64_t ex_multixmt;
unsigned ex_toolong;
unsigned ex_runt;
unsigned ex_oflo;
unsigned ex_fcs;
unsigned ex_align;
unsigned ex_allocbfail;
unsigned ex_txerr;
unsigned ex_uflo;
unsigned ex_jabber;
unsigned ex_excoll;
unsigned ex_sqe;
unsigned ex_nocarrier;
unsigned ex_multcol;
unsigned ex_defer;
unsigned ex_latecol;
unsigned ex_singlecol;
uint_t ex_conf; /* config flags */
#define CONF_INTPHY 0x0001 /* has internal PHY at address 24 */
#define CONF_90XB 0x0002 /* is 90xB */
} elxl_t;
#define WAIT_CMD(sc) \
{ \
int stat; \
do { \
stat = GET16(REG_CMD_STAT); \
} while ((stat & STAT_CMD_IN_PROGRESS) && (stat != 0xffff)); \
}
#define GET8(off) \
ddi_get8(sc->ex_regsh, (void *)(sc->ex_regsva + (off)))
#define GET16(off) \
ddi_get16(sc->ex_regsh, (void *)(sc->ex_regsva + (off)))
#define GET32(off) \
ddi_get32(sc->ex_regsh, (void *)(sc->ex_regsva + (off)))
#define PUT8(off, val) \
ddi_put8(sc->ex_regsh, (void *)(sc->ex_regsva + (off)), val)
#define PUT16(off, val) \
ddi_put16(sc->ex_regsh, (void *)(sc->ex_regsva + (off)), val)
#define PUT32(off, val) \
ddi_put32(sc->ex_regsh, (void *)(sc->ex_regsva + (off)), val)
#define SET16(off, val) PUT16(off, GET16(off) | val)
#define CLR16(off, val) PUT16(off, GET16(off) & ~(val))
#define PUT_CMD(x) PUT16(REG_CMD_STAT, (x))
#define SET_WIN(x) PUT16(REG_CMD_STAT, CMD_SELECT_WINDOW | (x))
#define PUT_PD(ring, member, val) ddi_put32(ring->r_acch, &member, (val))
#define GET_PD(ring, member) ddi_get32(ring->r_acch, &member)
#endif /* ELXL_H */