/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _BFE_H
#define _BFE_H
#include "bfe_hw.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BFE_SUCCESS DDI_SUCCESS
#define BFE_FAILURE DDI_FAILURE
#define BFE_MAX_MULTICAST_TABLE 64
#define BFE_LINK_SPEED_10MBS 1
#define BFE_LINK_SPEED_100MBS 2
#define VTAG_SIZE 4
#define BFE_MTU ETHERMTU
/*
* Use to increment descriptor slot number.
*/
#define BFE_INC_SLOT(i, p2) \
(i = ((i + 1) & (p2 - 1)))
#define BFE_DEC_SLOT(i, p2) \
(i = ((i + p2 - 1) % p2))
/*
* I/O instructions
*/
#define OUTB(bfe, p, v) \
ddi_put8((bfe)->bfe_mem_regset.hdl, \
(void *)((caddr_t)((bfe)->bfe_mem_regset.addr) + (p)), v)
#define OUTW(bfe, p, v) \
ddi_put16((bfe)->bfe_mem_regset.hdl, \
(void *)((caddr_t)((bfe)->bfe_mem_regset.addr) + (p)), v)
#define OUTL(bfe, p, v) \
ddi_put32((bfe)->bfe_mem_regset.hdl, \
(void *)((caddr_t)((bfe)->bfe_mem_regset.addr) + (p)), v)
#define INB(bfe, p) \
ddi_get8((bfe)->bfe_mem_regset.hdl, \
(void *)(((caddr_t)(bfe)->bfe_mem_regset.addr) + (p)))
#define INW(bfe, p) \
ddi_get16((bfe)->bfe_mem_regset.hdl, \
(void *)(((caddr_t)(bfe)->bfe_mem_regset.addr) + (p)))
#define INL(bfe, p) \
ddi_get32((bfe)->bfe_mem_regset.hdl, \
(void *)(((caddr_t)(bfe)->bfe_mem_regset.addr) + (p)))
#define FLUSH(bfe, reg) \
(void) INL(bfe, reg)
#define OUTL_OR(bfe, reg, v) \
OUTL(bfe, reg, (INL(bfe, reg) | v))
#define OUTL_AND(bfe, reg, v) \
OUTL(bfe, reg, (INL(bfe, reg) & v))
/*
* These macros allows use to write to descriptor memory.
*/
#define PUT_DESC(r, member, val) \
ddi_put32(r->r_desc_acc_handle, (member), (val))
#define GET_DESC(r, member) \
ddi_get32(r->r_desc_acc_handle, (member))
typedef struct bfe_cards {
uint16_t vendor_id;
uint16_t device_id;
char *cardname;
} bfe_cards_t;
/*
* Chip's state.
*/
typedef enum {
BFE_CHIP_UNINITIALIZED = 0,
BFE_CHIP_INITIALIZED,
BFE_CHIP_ACTIVE,
BFE_CHIP_STOPPED,
BFE_CHIP_HALT,
BFE_CHIP_RESUME,
BFE_CHIP_SUSPENDED,
BFE_CHIP_QUIESCED
} bfe_chip_state_t;
/*
* PHY state.
*/
typedef enum {
BFE_PHY_STARTED = 1,
BFE_PHY_STOPPED,
BFE_PHY_RESET_DONE,
BFE_PHY_RESET_TIMEOUT,
BFE_PHY_NOTFOUND
} bfe_phy_state_t;
/*
* Chip's mode
*/
#define BFE_RX_MODE_ENABLE 0x1
#define BFE_RX_MODE_PROMISC 0x2
#define BFE_RX_MODE_BROADCAST 0x4
#define BFE_RX_MODE_ALLMULTI 0x8
/*
* Every packet has this header which is put by the card.
*/
typedef struct bfe_rx_header {
uint16_t len;
uint16_t flags;
uint16_t pad[12];
} bfe_rx_header_t;
typedef struct bfe_stats {
uint64_t ether_stat_align_errors;
uint64_t ether_stat_carrier_errors;
uint64_t ether_stat_ex_collisions;
uint64_t ether_stat_fcs_errors;
uint64_t ether_stat_first_collisions;
uint64_t ether_stat_macrcv_errors;
uint64_t ether_stat_macxmt_errors;
uint64_t ether_stat_multi_collisions;
uint64_t ether_stat_toolong_errors;
uint64_t ether_stat_tooshort_errors;
uint64_t ether_stat_tx_late_collisions;
uint64_t ether_stat_defer_xmts;
uint64_t brdcstrcv;
uint64_t brdcstxmt;
uint64_t multixmt;
uint64_t collisions;
uint64_t ierrors;
uint64_t ipackets;
uint64_t multircv;
uint64_t norcvbuf;
uint64_t noxmtbuf;
uint64_t obytes;
uint64_t opackets;
uint64_t rbytes;
uint64_t underflows;
uint64_t overflows;
uint64_t txchecks;
uint64_t intr_claimed;
uint64_t intr_unclaimed;
uint64_t linkchanges;
uint64_t txcpybytes;
uint64_t txmapbytes;
uint64_t rxcpybytes;
uint64_t rxmapbytes;
uint64_t txreclaim0;
uint64_t txreclaims;
uint32_t txstalls;
uint32_t resets;
} bfe_stats_t;
typedef struct {
int state;
int speed;
int duplex;
int flowctrl;
int mau;
} bfe_link_t;
/*
* Device registers handle
*/
typedef struct {
ddi_acc_handle_t hdl;
caddr_t addr;
} bfe_acc_t;
/*
* BCM4401 Chip state
*/
typedef struct bfe_chip {
int link;
int state;
int speed;
int duplex;
uint32_t bmsr;
uint32_t phyaddr;
} bfe_chip_t;
/*
* Ring Management framework.
*/
/*
* TX and RX descriptor format in the hardware.
*/
typedef struct bfe_desc {
volatile uint32_t desc_ctl;
volatile uint32_t desc_addr;
} bfe_desc_t;
/*
* DMA handle for each descriptor
*/
typedef struct bfe_dma {
ddi_dma_handle_t handle;
ddi_acc_handle_t acchdl;
ddi_dma_cookie_t cookie;
caddr_t addr;
size_t len;
} bfe_dma_t;
/* Keep it power of 2 */
#define TX_NUM_DESC 128
#define RX_NUM_DESC 128
#define BFE_RING_UNALLOCATED 0
#define BFE_RING_ALLOCATED 1
struct bfe;
typedef struct bfe_ring {
/* Lock for the ring */
kmutex_t r_lock;
/* Actual lock pointer. It may point to global lock */
kmutex_t *r_lockp;
/* DMA handle for all buffers in descriptor table */
bfe_dma_t *r_buf_dma;
/* DMA buffer holding descriptor table */
bfe_desc_t *r_desc;
/* DMA handle for the descriptor table */
ddi_dma_handle_t r_desc_dma_handle;
ddi_acc_handle_t r_desc_acc_handle;
ddi_dma_cookie_t r_desc_cookie;
uint32_t r_ndesc; /* number of descriptors for the ring */
size_t r_desc_len; /* Actual descriptor size */
/* DMA buffer length */
size_t r_buf_len;
/* Flags associated to the ring */
int r_flags;
/* Pointer back to bfe instance */
struct bfe *r_bfe;
/* Current slot number (or descriptor number) in the ring */
uint_t r_curr_desc;
/* Consumed descriptor if got the interrupt (only used for TX) */
uint_t r_cons_desc;
uint_t r_avail_desc;
} bfe_ring_t;
/*
* Device driver's private data per instance.
*/
typedef struct bfe {
/* devinfo stuff */
dev_info_t *bfe_dip;
int bfe_unit;
/* PCI Configuration handle */
ddi_acc_handle_t bfe_conf_handle;
/* Device registers handle and regset */
bfe_acc_t bfe_mem_regset;
/* Ethernet addr */
ether_addr_t bfe_ether_addr;
ether_addr_t bfe_dev_addr;
/* MAC layer handle */
mac_handle_t bfe_machdl;
/* Interrupt management */
ddi_intr_handle_t bfe_intrhdl;
uint_t bfe_intrpri;
/* Ring Management */
bfe_ring_t bfe_tx_ring;
bfe_ring_t bfe_rx_ring;
int bfe_tx_resched;
/* Chip details */
bfe_chip_t bfe_chip;
bfe_stats_t bfe_stats;
bfe_chip_state_t bfe_chip_state;
uint_t bfe_chip_mode;
int32_t bfe_phy_addr;
uchar_t bfe_chip_action;
bfe_hw_stats_t bfe_hw_stats;
/* rw lock for chip */
krwlock_t bfe_rwlock;
/* Multicast table */
uint32_t bfe_mcast_cnt;
/* Timeout and PHY state */
ddi_periodic_t bfe_periodic_id;
hrtime_t bfe_tx_stall_time;
bfe_phy_state_t bfe_phy_state;
int bfe_phy_id;
/* MII register set */
uint16_t bfe_mii_exp;
uint16_t bfe_mii_bmsr;
uint16_t bfe_mii_anar;
uint16_t bfe_mii_anlpar;
uint16_t bfe_mii_bmcr;
/* Transceiver fields */
uint8_t bfe_adv_aneg;
uint8_t bfe_adv_100T4;
uint8_t bfe_adv_100fdx;
uint8_t bfe_adv_100hdx;
uint8_t bfe_adv_10fdx;
uint8_t bfe_adv_10hdx;
uint8_t bfe_cap_aneg;
uint8_t bfe_cap_100T4;
uint8_t bfe_cap_100fdx;
uint8_t bfe_cap_100hdx;
uint8_t bfe_cap_10fdx;
uint8_t bfe_cap_10hdx;
} bfe_t;
static int bfe_identify_hardware(bfe_t *);
#ifdef __cplusplus
}
#endif
#endif /* _BFE_H */