Skip to content

Commit

Permalink
Transmit is working! Link checking disabled for now (reboot issue).
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Wyatt authored and Daniel Wyatt committed Jul 13, 2012
1 parent de83eb2 commit b7f903e
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 30 deletions.
89 changes: 68 additions & 21 deletions src/drivers/net/bnx2.c
Expand Up @@ -39,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
* bnx2 network driver
*
*/

static uint32_t bnx2_reg_read_indirect ( struct bnx2_nic *bnx2,
uint32_t offset ) {
uint32_t value;
Expand Down Expand Up @@ -90,30 +91,30 @@ static void bnx2_set_mac_address ( struct bnx2_nic *bnx2,

/* We use the lower 3 bytes as the back-off seed */
value = netdev->hw_addr[5] + netdev->hw_addr[4] + netdev->hw_addr[3];
value |= BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED;
value &= BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED;
writel ( value, bnx2->regs + BNX2_EMAC_BACKOFF_SEED );
}

static int bnx2_alloc_mem ( struct bnx2_nic *bnx2 ) {
bnx2->status_blk = malloc_dma ( sizeof ( struct status_block ),
sizeof ( struct status_block ) );
bnx2->tx_ring.tx_desc_ring = malloc_dma ( sizeof ( struct tx_bd ),
sizeof ( struct tx_bd ) );
bnx2->tx_ring.tx_desc_ring = malloc_dma ( sizeof ( struct bnx2_tx_bd ) * TX_DESC_CNT,
sizeof ( struct bnx2_tx_bd ) );
if ( !bnx2->status_blk || !bnx2->tx_ring.tx_desc_ring ) {
/* These are zeroed earlier so this is safe */
free_dma ( bnx2->status_blk, sizeof ( struct status_block ) );
free_dma ( bnx2->tx_ring.tx_desc_ring, sizeof ( struct tx_bd ) );
free_dma ( bnx2->tx_ring.tx_desc_ring, sizeof ( struct bnx2_tx_bd ) );
return -ENOMEM;
}
memset ( bnx2->status_blk, 0, sizeof ( struct status_block ) );
memset ( bnx2->tx_ring.tx_desc_ring, 0, sizeof ( struct tx_bd ) );
memset ( bnx2->tx_ring.tx_desc_ring, 0, sizeof ( struct bnx2_tx_bd ) * TX_DESC_CNT );
return 0;
}

static void bnx2_free_mem ( struct bnx2_nic *bnx2 ) {
free_dma ( bnx2->status_blk, sizeof ( struct status_block ) );
bnx2->status_blk = NULL;
free_dma ( bnx2->tx_ring.tx_desc_ring, sizeof ( struct tx_bd ) );
free_dma ( bnx2->tx_ring.tx_desc_ring, sizeof ( struct bnx2_tx_bd ) );
bnx2->tx_ring.tx_desc_ring = NULL;
}

Expand Down Expand Up @@ -336,6 +337,7 @@ static void bnx2_load_mips_firmware ( struct bnx2_nic *bnx2,
static void bnx2_load_firmware ( struct bnx2_nic *bnx2 ) {
const uint32_t *rv2p_firmware;
const uint32_t *mips_firmware;

if ( CHIP_NUM ( bnx2->misc_id ) == CHIP_NUM_5709 ) {
if ( CHIP_ID ( bnx2->misc_id ) == CHIP_ID_5709_A0 ||
CHIP_ID ( bnx2->misc_id ) == CHIP_ID_5709_A1 )
Expand Down Expand Up @@ -453,9 +455,10 @@ static int bnx2_init_chip ( struct bnx2_nic *bnx2 ) {
return rc;

writel ( BNX2_MISC_ENABLE_DEFAULT, bnx2->regs + BNX2_MISC_ENABLE_SET_BITS );
writel ( BNX2_HC_COMMAND_ENABLE | BNX2_HC_COMMAND_COAL_NOW_WO_INT, bnx2->regs + BNX2_HC_COMMAND );
readl ( bnx2->regs + BNX2_MISC_ENABLE_SET_BITS );
writel ( BNX2_HC_COMMAND_ENABLE | BNX2_HC_COMMAND_COAL_NOW_WO_INT, bnx2->regs + BNX2_HC_COMMAND );
udelay ( 20 );
bnx2->hc_cmd = readl ( bnx2->regs + BNX2_HC_COMMAND );
return 0;
}

Expand Down Expand Up @@ -488,10 +491,9 @@ static void bnx2_init_tx_context ( struct bnx2_nic *bnx2 ) {
}

static void bnx2_init_rings ( struct bnx2_nic *bnx2 ) {
struct tx_bd *txbd = bnx2->tx_ring.tx_desc_ring;
struct bnx2_tx_bd *txbd = bnx2->tx_ring.tx_desc_ring;

txbd->tx_bd_haddr_hi = ( uint64_t ) virt_to_bus ( bnx2->tx_ring.tx_desc_ring ) >> 32;
txbd->tx_bd_haddr_lo = ( uint64_t ) virt_to_bus ( bnx2->tx_ring.tx_desc_ring ) & 0xffffffff;
txbd->haddr = virt_to_bus ( bnx2->tx_ring.tx_desc_ring );
bnx2->tx_ring.tx_prod = 0;
bnx2->tx_ring.tx_prod_bseq = 0;
bnx2_init_tx_context ( bnx2 );
Expand All @@ -511,12 +513,17 @@ static int bnx2_reset_nic ( struct bnx2_nic *bnx2 ) {

static int bnx2_init_nic ( struct bnx2_nic *bnx2 ) {
int rc;
uint32_t value;

if ( ( rc = bnx2_reset_nic ( bnx2 ) ) != 0 )
return rc;

value = readl ( bnx2->regs + BNX2_EMAC_MODE );
value |= BNX2_EMAC_MODE_PORT_GMII;
writel ( value, bnx2->regs + BNX2_EMAC_MODE );
return 0;
}

/******************************************************************************
*
* MII interface
Expand Down Expand Up @@ -628,6 +635,7 @@ static struct mii_operations bnx2_mii_operations = {
*/
static int bnx2_reset ( struct bnx2_nic *bnx2 ) {
uint32_t value;

writel ( BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP,
bnx2->regs + BNX2_PCICFG_MISC_CONFIG );
Expand Down Expand Up @@ -658,7 +666,25 @@ static int bnx2_reset ( struct bnx2_nic *bnx2 ) {
*/
static void bnx2_check_link ( struct net_device *netdev ) {
struct bnx2_nic *bnx2 = netdev->priv;
( void ) bnx2;
struct status_block *status_blk = bnx2->status_blk;
uint32_t status_idx = status_blk->status_idx;
uint32_t new_link = bnx2->status_blk->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE;
uint32_t old_link = bnx2->status_blk->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE;

if ( new_link != old_link ) {
if ( new_link ) {
writel ( STATUS_ATTN_BITS_LINK_STATE, bnx2->regs + BNX2_PCICFG_STATUS_BIT_SET_CMD );
netdev_link_up ( netdev );
}
else {
writel ( STATUS_ATTN_BITS_LINK_STATE, bnx2->regs + BNX2_PCICFG_STATUS_BIT_CLEAR_CMD );
netdev_link_down ( netdev );
}
//writel ( BNX2_PCICFG_INT_ACK_CMD_MASK_INT | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | status_idx, bnx2->regs + BNX2_PCICFG_INT_ACK_CMD );
//writel ( BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | status_idx, bnx2->regs + BNX2_PCICFG_INT_ACK_CMD );
writel ( bnx2->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT, bnx2->regs + BNX2_HC_COMMAND );
readl ( bnx2->regs + BNX2_HC_COMMAND );
}
}

/******************************************************************************
Expand All @@ -678,12 +704,10 @@ static int bnx2_open ( struct net_device *netdev ) {
struct bnx2_nic *bnx2 = netdev->priv;
int rc;

if ( ( rc = bnx2_alloc_mem ( bnx2 ) ) )
return rc;

if ( ( rc = bnx2_init_nic ( bnx2 ) ) )
return rc;

bnx2_check_link ( netdev );
return 0;
}

Expand All @@ -694,7 +718,7 @@ static int bnx2_open ( struct net_device *netdev ) {
*/
static void bnx2_close ( struct net_device *netdev ) {
struct bnx2_nic *bnx2 = netdev->priv;
bnx2_free_mem ( bnx2 );
( void ) bnx2;
}

/**
Expand All @@ -707,10 +731,26 @@ static void bnx2_close ( struct net_device *netdev ) {
static int bnx2_transmit ( struct net_device *netdev,
struct io_buffer *iobuf ) {
struct bnx2_nic *bnx2 = netdev->priv;

DBGC ( bnx2, "BNX2 %p does not yet support transmit\n", bnx2 );
( void ) iobuf;
return -ENOTSUP;
struct bnx2_tx_ring_info *txr = &bnx2->tx_ring;
struct bnx2_tx_bd *txbd;
unsigned int tx_idx;
unsigned int tx_tail;

if ( ( txr->tx_prod - txr->tx_cons ) >= TX_DESC_CNT ) {
DBGC ( bnx2, "BNX2 %p out of transmit descriptors\n", bnx2 );
return -ENOBUFS;
}
tx_idx = ( txr->tx_prod++ % TX_DESC_CNT );
tx_tail = ( txr->tx_prod % TX_DESC_CNT );
txbd = &txr->tx_desc_ring[tx_idx];
txbd->haddr = ( ( uint64_t ) virt_to_bus ( iobuf->data ) ) << 32;
txbd->reserved = iob_len ( iobuf );
txbd->vlan_tag = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
wmb();
txr->tx_prod_bseq += iob_len ( iobuf );
writew ( tx_tail, bnx2->regs + MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX );
writel ( txr->tx_prod_bseq, bnx2->regs + MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ );
return 0;
}

/**
Expand All @@ -720,9 +760,8 @@ static int bnx2_transmit ( struct net_device *netdev,
*/
static void bnx2_poll ( struct net_device *netdev ) {
struct bnx2_nic *bnx2 = netdev->priv;

/* Not yet implemented */
( void ) bnx2;
bnx2_check_link ( netdev );
}

/**
Expand Down Expand Up @@ -784,6 +823,8 @@ static int bnx2_probe ( struct pci_device *pci ) {

/* Map registers */
bnx2->regs = ioremap ( pci->membase, BNX2_BAR_SIZE );
if ( ( rc = bnx2_alloc_mem ( bnx2 ) ) )
goto err_alloc;

/* Reset the NIC */
if ( ( rc = bnx2_reset ( bnx2 ) ) != 0 )
Expand All @@ -792,11 +833,13 @@ static int bnx2_probe ( struct pci_device *pci ) {
bnx2_set_mac_address ( bnx2, netdev );
/* Initialise and reset MII interface */
mii_init ( &bnx2->mii, &bnx2_mii_operations );
/*
if ( ( rc = mii_reset ( &bnx2->mii ) ) != 0 ) {
DBGC ( bnx2, "BNX2 %p could not reset MII: %s\n",
bnx2, strerror ( rc ) );
goto err_mii_reset;
}
*/
/* Register network device */
if ( ( rc = register_netdev ( netdev ) ) != 0 )
goto err_register_netdev;
Expand All @@ -808,8 +851,10 @@ static int bnx2_probe ( struct pci_device *pci ) {

unregister_netdev ( netdev );
err_register_netdev:
/*
err_mii_reset:
bnx2_reset ( bnx2 );
*/
err_reset:
netdev_nullify ( netdev );
netdev_put ( netdev );
Expand All @@ -832,6 +877,8 @@ static void bnx2_remove ( struct pci_device *pci ) {
/* Reset card */
bnx2_reset ( bnx2 );

bnx2_free_mem ( bnx2 );

/* Free network device */
netdev_nullify ( netdev );
netdev_put ( netdev );
Expand Down
45 changes: 36 additions & 9 deletions src/drivers/net/bnx2.h
Expand Up @@ -20,6 +20,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define RV2P_PROC1 0
#define RV2P_PROC2 1



#define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078

#define BNX2_PCICFG_REG_WINDOW 0x00000080
Expand Down Expand Up @@ -140,6 +142,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050
#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054

#define BNX2_EMAC_MODE 0x00001400
#define BNX2_EMAC_MODE_PORT_GMII ( 2L << 2 )

#define BNX2_EMAC_MDIO_COMM 0x000014ac
#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE ( 1L << 26 )
#define BNX2_EMAC_MDIO_COMM_COMMAND_READ ( 2L << 26 )
Expand All @@ -150,6 +155,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED ( 0x3ffL << 0 )

#define BNX2_PCICFG_INT_ACK_CMD 0x00000084
#define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID ( 1L << 16 )
#define BNX2_PCICFG_INT_ACK_CMD_MASK_INT ( 1L << 18 )

#define BNX2_HOST_VIEW_SHMEM_BASE 0x00167c00
Expand Down Expand Up @@ -191,7 +197,7 @@ FILE_LICENCE ( GPL2_OR_LATER );

#define BNX2_CTX_VIRT_ADDR 0x00001008

#define BNX2_CTX_PAGE_TBL 0x00001010
#define BNX2_CTX_PAGE_TBL 0x0000100c

#define CTX_SHIFT 7
#define CTX_SIZE ( 1 << CTX_SHIFT )
Expand Down Expand Up @@ -229,7 +235,26 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define BNX2_L2CTX_TYPE_SIZE_L2 ( ( 0xc0 / 0x20 ) << 16 )
#define BNX2_L2CTX_TYPE_TYPE_L2 ( 1 << 28 )

#define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088
#define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c

#define BNX2_L2CTX_TX_HOST_BIDX 0x00000088
#define BNX2_L2CTX_TX_HOST_BSEQ 0x00000090

#define TX_DESC_CNT ( BCM_PAGE_SIZE / sizeof ( struct bnx2_tx_bd ) )
#define MAX_TX_DESC_CNT ( TX_DESC_CNT - 1 )

#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
(MAX_TX_DESC_CNT - 1)) ? \
(x) + 2 : (x) + 1

#define MB_KERNEL_CTX_SHIFT 8
#define MB_KERNEL_CTX_SIZE ( 1 << MB_KERNEL_CTX_SHIFT )
#define MB_KERNEL_CTX_MASK ( MB_KERNEL_CTX_SIZE - 1 )
#define MB_GET_CID_ADDR(_cid) ( 0x10000 + ( ( _cid ) << MB_KERNEL_CTX_SHIFT ) )

#define TX_CID 16
#define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID)

struct status_block {
uint32_t status_attn_bits;
Expand Down Expand Up @@ -320,20 +345,21 @@ struct status_block {
#endif
};

struct tx_bd {
uint32_t tx_bd_haddr_hi;
uint32_t tx_bd_haddr_lo;
uint32_t tx_bd_mss_nbytes;
uint32_t tx_bd_vlan_tag_flags;
struct bnx2_tx_bd {
uint64_t haddr;
uint16_t reserved;
uint16_t nbytes;
uint16_t vlan_tag;
uint16_t flags;
#define TX_BD_FLAGS_END ( 1 << 6 )
#define TX_BD_FLAGS_START ( 1 << 7 )
};
} __attribute__ (( packed ));

struct bnx2_tx_ring_info {
uint32_t tx_prod_bseq;
uint16_t tx_prod;

struct tx_bd *tx_desc_ring;
uint16_t tx_cons;
struct bnx2_tx_bd *tx_desc_ring;
};

/** A bnx2 network card */
Expand All @@ -357,6 +383,7 @@ struct bnx2_nic {
uint32_t phy_addr;

struct net_device *netdev;
uint32_t hc_cmd;

/** MII interface */
struct mii_interface mii;
Expand Down

0 comments on commit b7f903e

Please sign in to comment.