2006-10-21 23:33:03 +04:00
/*
* Copyright ( C ) 2003 - 2006 NetXen , Inc .
* All rights reserved .
2006-12-04 20:18:00 +03:00
*
2006-10-21 23:33:03 +04:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2006-11-29 20:00:10 +03:00
*
2006-10-21 23:33:03 +04:00
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2006-11-29 20:00:10 +03:00
*
2006-10-21 23:33:03 +04:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston ,
* MA 02111 - 1307 , USA .
2006-12-04 20:18:00 +03:00
*
2006-10-21 23:33:03 +04:00
* The full GNU General Public License is included in this distribution
* in the file called LICENSE .
2006-12-04 20:18:00 +03:00
*
2006-10-21 23:33:03 +04:00
* Contact Information :
* info @ netxen . com
* NetXen ,
* 3965 Freedom Circle , Fourth floor ,
* Santa Clara , CA 95054
*
*
* Source file for NIC routines to access the Phantom hardware
*
*/
# include "netxen_nic.h"
# include "netxen_nic_hw.h"
# include "netxen_nic_phan_reg.h"
2007-04-20 18:52:37 +04:00
2007-03-13 02:09:15 +03:00
# include <net/ip.h>
2007-04-20 18:52:37 +04:00
struct netxen_recv_crb recv_crb_registers [ ] = {
/*
* Instance 0.
*/
{
2008-07-22 06:44:00 +04:00
/* crb_rcv_producer: */
{
NETXEN_NIC_REG ( 0x100 ) ,
/* Jumbo frames */
NETXEN_NIC_REG ( 0x110 ) ,
/* LRO */
NETXEN_NIC_REG ( 0x120 )
} ,
/* crb_sts_consumer: */
NETXEN_NIC_REG ( 0x138 ) ,
} ,
2007-04-20 18:52:37 +04:00
/*
* Instance 1 ,
*/
{
2008-07-22 06:44:00 +04:00
/* crb_rcv_producer: */
{
NETXEN_NIC_REG ( 0x144 ) ,
/* Jumbo frames */
NETXEN_NIC_REG ( 0x154 ) ,
/* LRO */
NETXEN_NIC_REG ( 0x164 )
} ,
/* crb_sts_consumer: */
NETXEN_NIC_REG ( 0x17c ) ,
} ,
2007-04-20 18:53:52 +04:00
/*
2007-04-20 18:55:26 +04:00
* Instance 2 ,
2007-04-20 18:53:52 +04:00
*/
{
2008-07-22 06:44:00 +04:00
/* crb_rcv_producer: */
{
NETXEN_NIC_REG ( 0x1d8 ) ,
/* Jumbo frames */
NETXEN_NIC_REG ( 0x1f8 ) ,
/* LRO */
NETXEN_NIC_REG ( 0x208 )
} ,
/* crb_sts_consumer: */
NETXEN_NIC_REG ( 0x220 ) ,
2007-04-20 18:53:52 +04:00
} ,
/*
2007-04-20 18:55:26 +04:00
* Instance 3 ,
2007-04-20 18:53:52 +04:00
*/
{
2008-07-22 06:44:00 +04:00
/* crb_rcv_producer: */
{
NETXEN_NIC_REG ( 0x22c ) ,
/* Jumbo frames */
NETXEN_NIC_REG ( 0x23c ) ,
/* LRO */
NETXEN_NIC_REG ( 0x24c )
} ,
/* crb_sts_consumer: */
NETXEN_NIC_REG ( 0x264 ) ,
2007-04-20 18:53:52 +04:00
} ,
2007-04-20 18:52:37 +04:00
} ;
2007-11-05 20:07:31 +03:00
static u64 ctx_addr_sig_regs [ ] [ 3 ] = {
2007-04-20 18:52:37 +04:00
{ NETXEN_NIC_REG ( 0x188 ) , NETXEN_NIC_REG ( 0x18c ) , NETXEN_NIC_REG ( 0x1c0 ) } ,
{ NETXEN_NIC_REG ( 0x190 ) , NETXEN_NIC_REG ( 0x194 ) , NETXEN_NIC_REG ( 0x1c4 ) } ,
{ NETXEN_NIC_REG ( 0x198 ) , NETXEN_NIC_REG ( 0x19c ) , NETXEN_NIC_REG ( 0x1c8 ) } ,
{ NETXEN_NIC_REG ( 0x1a0 ) , NETXEN_NIC_REG ( 0x1a4 ) , NETXEN_NIC_REG ( 0x1cc ) }
} ;
2007-11-05 20:07:31 +03:00
# define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0])
# define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2])
# define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1])
2007-04-20 18:52:37 +04:00
2006-10-21 23:33:03 +04:00
/* PCI Windowing for DDR regions. */
# define ADDR_IN_RANGE(addr, low, high) \
( ( ( addr ) < = ( high ) ) & & ( ( addr ) > = ( low ) ) )
2007-06-07 15:36:36 +04:00
# define NETXEN_FLASH_BASE (NETXEN_BOOTLD_START)
2006-10-21 23:33:03 +04:00
# define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE)
2006-12-04 20:23:25 +03:00
# define NETXEN_MAX_MTU 8000 + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE
2006-11-29 20:00:10 +03:00
# define NETXEN_MIN_MTU 64
2006-10-21 23:33:03 +04:00
# define NETXEN_ETH_FCS_SIZE 4
# define NETXEN_ENET_HEADER_SIZE 14
2006-11-29 20:00:10 +03:00
# define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */
2006-10-21 23:33:03 +04:00
# define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4)
# define NETXEN_NIU_HDRSIZE (0x1 << 6)
# define NETXEN_NIU_TLRSIZE (0x1 << 5)
2006-11-29 20:00:10 +03:00
# define lower32(x) ((u32)((x) & 0xffffffff))
# define upper32(x) \
( ( u32 ) ( ( ( unsigned long long ) ( x ) > > 32 ) & 0xffffffff ) )
# define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL
# define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL
# define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL
# define NETXEN_NIC_EPG_PAUSE_ADDR2 0x0100088866554433ULL
# define NETXEN_NIC_WINDOW_MARGIN 0x100000
2007-11-05 20:07:31 +03:00
static unsigned long netxen_nic_pci_set_window ( struct netxen_adapter * adapter ,
unsigned long long addr ) ;
2006-10-21 23:33:03 +04:00
void netxen_free_hw_resources ( struct netxen_adapter * adapter ) ;
int netxen_nic_set_mac ( struct net_device * netdev , void * p )
{
2007-04-20 18:52:37 +04:00
struct netxen_adapter * adapter = netdev_priv ( netdev ) ;
2006-10-21 23:33:03 +04:00
struct sockaddr * addr = p ;
if ( netif_running ( netdev ) )
return - EBUSY ;
if ( ! is_valid_ether_addr ( addr - > sa_data ) )
return - EADDRNOTAVAIL ;
memcpy ( netdev - > dev_addr , addr - > sa_data , netdev - > addr_len ) ;
2006-12-04 20:18:00 +03:00
if ( adapter - > macaddr_set )
2007-04-20 18:52:37 +04:00
adapter - > macaddr_set ( adapter , addr - > sa_data ) ;
2006-10-21 23:33:03 +04:00
return 0 ;
}
2008-07-22 06:44:01 +04:00
# define NETXEN_UNICAST_ADDR(port, index) \
( NETXEN_UNICAST_ADDR_BASE + ( port * 32 ) + ( index * 8 ) )
# define NETXEN_MCAST_ADDR(port, index) \
( NETXEN_MULTICAST_ADDR_BASE + ( port * 0x80 ) + ( index * 8 ) )
# define MAC_HI(addr) \
( ( addr [ 2 ] < < 16 ) | ( addr [ 1 ] < < 8 ) | ( addr [ 0 ] ) )
# define MAC_LO(addr) \
( ( addr [ 5 ] < < 16 ) | ( addr [ 4 ] < < 8 ) | ( addr [ 3 ] ) )
static int
netxen_nic_enable_mcast_filter ( struct netxen_adapter * adapter )
{
u32 val = 0 ;
u16 port = adapter - > physical_port ;
u8 * addr = adapter - > netdev - > dev_addr ;
if ( adapter - > mc_enabled )
return 0 ;
netxen_nic_hw_read_wx ( adapter , NETXEN_MAC_ADDR_CNTL_REG , & val , 4 ) ;
val | = ( 1UL < < ( 28 + port ) ) ;
netxen_nic_hw_write_wx ( adapter , NETXEN_MAC_ADDR_CNTL_REG , & val , 4 ) ;
/* add broadcast addr to filter */
val = 0xffffff ;
netxen_crb_writelit_adapter ( adapter , NETXEN_UNICAST_ADDR ( port , 0 ) , val ) ;
netxen_crb_writelit_adapter ( adapter ,
NETXEN_UNICAST_ADDR ( port , 0 ) + 4 , val ) ;
/* add station addr to filter */
val = MAC_HI ( addr ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_UNICAST_ADDR ( port , 1 ) , val ) ;
val = MAC_LO ( addr ) ;
netxen_crb_writelit_adapter ( adapter ,
NETXEN_UNICAST_ADDR ( port , 1 ) + 4 , val ) ;
adapter - > mc_enabled = 1 ;
return 0 ;
}
static int
netxen_nic_disable_mcast_filter ( struct netxen_adapter * adapter )
{
u32 val = 0 ;
u16 port = adapter - > physical_port ;
u8 * addr = adapter - > netdev - > dev_addr ;
if ( ! adapter - > mc_enabled )
return 0 ;
netxen_nic_hw_read_wx ( adapter , NETXEN_MAC_ADDR_CNTL_REG , & val , 4 ) ;
val & = ~ ( 1UL < < ( 28 + port ) ) ;
netxen_nic_hw_write_wx ( adapter , NETXEN_MAC_ADDR_CNTL_REG , & val , 4 ) ;
val = MAC_HI ( addr ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_UNICAST_ADDR ( port , 0 ) , val ) ;
val = MAC_LO ( addr ) ;
netxen_crb_writelit_adapter ( adapter ,
NETXEN_UNICAST_ADDR ( port , 0 ) + 4 , val ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_UNICAST_ADDR ( port , 1 ) , 0 ) ;
netxen_crb_writelit_adapter ( adapter , NETXEN_UNICAST_ADDR ( port , 1 ) + 4 , 0 ) ;
adapter - > mc_enabled = 0 ;
return 0 ;
}
static int
netxen_nic_set_mcast_addr ( struct netxen_adapter * adapter ,
int index , u8 * addr )
{
u32 hi = 0 , lo = 0 ;
u16 port = adapter - > physical_port ;
lo = MAC_LO ( addr ) ;
hi = MAC_HI ( addr ) ;
netxen_crb_writelit_adapter ( adapter ,
NETXEN_MCAST_ADDR ( port , index ) , hi ) ;
netxen_crb_writelit_adapter ( adapter ,
NETXEN_MCAST_ADDR ( port , index ) + 4 , lo ) ;
return 0 ;
}
2006-10-21 23:33:03 +04:00
/*
* netxen_nic_set_multi - Multicast
*/
void netxen_nic_set_multi ( struct net_device * netdev )
{
2007-04-20 18:52:37 +04:00
struct netxen_adapter * adapter = netdev_priv ( netdev ) ;
2006-10-21 23:33:03 +04:00
struct dev_mc_list * mc_ptr ;
2008-07-22 06:44:01 +04:00
u8 null_addr [ 6 ] ;
int index = 0 ;
memset ( null_addr , 0 , 6 ) ;
2006-10-21 23:33:03 +04:00
if ( netdev - > flags & IFF_PROMISC ) {
2008-07-22 06:44:01 +04:00
adapter - > set_promisc ( adapter ,
NETXEN_NIU_PROMISC_MODE ) ;
/* Full promiscuous mode */
netxen_nic_disable_mcast_filter ( adapter ) ;
return ;
}
if ( netdev - > mc_count = = 0 ) {
adapter - > set_promisc ( adapter ,
NETXEN_NIU_NON_PROMISC_MODE ) ;
netxen_nic_disable_mcast_filter ( adapter ) ;
return ;
}
adapter - > set_promisc ( adapter , NETXEN_NIU_ALLMULTI_MODE ) ;
if ( netdev - > flags & IFF_ALLMULTI | |
netdev - > mc_count > adapter - > max_mc_count ) {
netxen_nic_disable_mcast_filter ( adapter ) ;
return ;
2006-10-21 23:33:03 +04:00
}
2008-07-22 06:44:01 +04:00
netxen_nic_enable_mcast_filter ( adapter ) ;
for ( mc_ptr = netdev - > mc_list ; mc_ptr ; mc_ptr = mc_ptr - > next , index + + )
netxen_nic_set_mcast_addr ( adapter , index , mc_ptr - > dmi_addr ) ;
if ( index ! = netdev - > mc_count )
printk ( KERN_WARNING " %s: %s multicast address count mismatch \n " ,
netxen_nic_driver_name , netdev - > name ) ;
/* Clear out remaining addresses */
for ( ; index < adapter - > max_mc_count ; index + + )
netxen_nic_set_mcast_addr ( adapter , index , null_addr ) ;
2006-10-21 23:33:03 +04:00
}
/*
* netxen_nic_change_mtu - Change the Maximum Transfer Unit
* @ returns 0 on success , negative on failure
*/
int netxen_nic_change_mtu ( struct net_device * netdev , int mtu )
{
2007-04-20 18:52:37 +04:00
struct netxen_adapter * adapter = netdev_priv ( netdev ) ;
2006-10-21 23:33:03 +04:00
int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE ;
if ( ( eff_mtu > NETXEN_MAX_MTU ) | | ( eff_mtu < NETXEN_MIN_MTU ) ) {
printk ( KERN_ERR " %s: %s %d is not supported. \n " ,
netxen_nic_driver_name , netdev - > name , mtu ) ;
return - EINVAL ;
}
2006-12-04 20:18:00 +03:00
if ( adapter - > set_mtu )
2007-04-20 18:52:37 +04:00
adapter - > set_mtu ( adapter , mtu ) ;
2006-10-21 23:33:03 +04:00
netdev - > mtu = mtu ;
return 0 ;
}
/*
* check if the firmware has been downloaded and ready to run and
* setup the address for the descriptors in the adapter
*/
int netxen_nic_hw_resources ( struct netxen_adapter * adapter )
{
struct netxen_hardware_context * hw = & adapter - > ahw ;
u32 state = 0 ;
void * addr ;
int loops = 0 , err = 0 ;
int ctx , ring ;
struct netxen_recv_context * recv_ctx ;
struct netxen_rcv_desc_ctx * rcv_desc ;
2007-04-20 18:53:52 +04:00
int func_id = adapter - > portnum ;
2006-10-21 23:33:03 +04:00
2006-12-04 20:18:00 +03:00
DPRINTK ( INFO , " crb_base: %lx %x " , NETXEN_PCI_CRBSPACE ,
2006-11-29 20:00:10 +03:00
PCI_OFFSET_SECOND_RANGE ( adapter , NETXEN_PCI_CRBSPACE ) ) ;
2006-12-04 20:18:00 +03:00
DPRINTK ( INFO , " cam base: %lx %x " , NETXEN_CRB_CAM ,
2006-11-29 20:00:10 +03:00
pci_base_offset ( adapter , NETXEN_CRB_CAM ) ) ;
2006-12-04 20:18:00 +03:00
DPRINTK ( INFO , " cam RAM: %lx %x " , NETXEN_CAM_RAM_BASE ,
2006-11-29 20:00:10 +03:00
pci_base_offset ( adapter , NETXEN_CAM_RAM_BASE ) ) ;
2006-10-21 23:33:03 +04:00
for ( ctx = 0 ; ctx < MAX_RCV_CTX ; + + ctx ) {
DPRINTK ( INFO , " Command Peg ready..waiting for rcv peg \n " ) ;
loops = 0 ;
state = 0 ;
/* Window 1 call */
2008-07-22 06:44:00 +04:00
state = readl ( NETXEN_CRB_NORMALIZE ( adapter , CRB_RCVPEG_STATE ) ) ;
2006-10-21 23:33:03 +04:00
while ( state ! = PHAN_PEG_RCV_INITIALIZED & & loops < 20 ) {
2007-07-02 08:07:57 +04:00
msleep ( 1 ) ;
2006-10-21 23:33:03 +04:00
/* Window 1 call */
state = readl ( NETXEN_CRB_NORMALIZE ( adapter ,
2008-07-22 06:44:00 +04:00
CRB_RCVPEG_STATE ) ) ;
2006-10-21 23:33:03 +04:00
loops + + ;
}
if ( loops > = 20 ) {
printk ( KERN_ERR " Rcv Peg initialization not complete: "
" %x. \n " , state ) ;
err = - EIO ;
return err ;
}
}
2007-07-01 22:56:00 +04:00
adapter - > intr_scheme = readl (
NETXEN_CRB_NORMALIZE ( adapter , CRB_NIC_CAPABILITIES_FW ) ) ;
2008-03-18 05:59:48 +03:00
adapter - > msi_mode = readl (
NETXEN_CRB_NORMALIZE ( adapter , CRB_NIC_MSI_MODE_FW ) ) ;
2006-10-21 23:33:03 +04:00
2008-07-22 06:44:00 +04:00
addr = pci_alloc_consistent ( adapter - > pdev ,
sizeof ( struct netxen_ring_ctx ) + sizeof ( uint32_t ) ,
& adapter - > ctx_desc_phys_addr ) ;
2006-11-29 20:00:10 +03:00
2006-10-21 23:33:03 +04:00
if ( addr = = NULL ) {
DPRINTK ( ERR , " bad return from pci_alloc_consistent \n " ) ;
2006-12-04 20:23:25 +03:00
err = - ENOMEM ;
return err ;
2006-11-29 20:00:10 +03:00
}
2006-12-04 20:23:25 +03:00
memset ( addr , 0 , sizeof ( struct netxen_ring_ctx ) ) ;
adapter - > ctx_desc = ( struct netxen_ring_ctx * ) addr ;
2007-04-20 18:55:26 +04:00
adapter - > ctx_desc - > ctx_id = cpu_to_le32 ( adapter - > portnum ) ;
2007-01-02 13:39:10 +03:00
adapter - > ctx_desc - > cmd_consumer_offset =
cpu_to_le64 ( adapter - > ctx_desc_phys_addr +
sizeof ( struct netxen_ring_ctx ) ) ;
2007-12-22 22:44:00 +03:00
adapter - > cmd_consumer = ( __le32 * ) ( ( ( char * ) addr ) +
2006-12-04 20:23:25 +03:00
sizeof ( struct netxen_ring_ctx ) ) ;
2008-07-22 06:44:00 +04:00
addr = pci_alloc_consistent ( adapter - > pdev ,
2007-02-21 17:37:06 +03:00
sizeof ( struct cmd_desc_type0 ) *
adapter - > max_tx_desc_count ,
2008-07-22 06:44:00 +04:00
& hw - > cmd_desc_phys_addr ) ;
2006-11-29 20:00:10 +03:00
2006-12-04 20:23:25 +03:00
if ( addr = = NULL ) {
DPRINTK ( ERR , " bad return from pci_alloc_consistent \n " ) ;
netxen_free_hw_resources ( adapter ) ;
2006-11-29 20:00:10 +03:00
return - ENOMEM ;
2006-10-21 23:33:03 +04:00
}
2007-01-02 13:39:10 +03:00
adapter - > ctx_desc - > cmd_ring_addr =
cpu_to_le64 ( hw - > cmd_desc_phys_addr ) ;
adapter - > ctx_desc - > cmd_ring_size =
cpu_to_le32 ( adapter - > max_tx_desc_count ) ;
2006-10-21 23:33:03 +04:00
hw - > cmd_desc_head = ( struct cmd_desc_type0 * ) addr ;
for ( ctx = 0 ; ctx < MAX_RCV_CTX ; + + ctx ) {
recv_ctx = & adapter - > recv_ctx [ ctx ] ;
for ( ring = 0 ; ring < NUM_RCV_DESC_RINGS ; ring + + ) {
rcv_desc = & recv_ctx - > rcv_desc [ ring ] ;
2008-07-22 06:44:00 +04:00
addr = pci_alloc_consistent ( adapter - > pdev ,
2006-11-29 20:00:10 +03:00
RCV_DESC_RINGSIZE ,
2008-07-22 06:44:00 +04:00
& rcv_desc - > phys_addr ) ;
2006-10-21 23:33:03 +04:00
if ( addr = = NULL ) {
DPRINTK ( ERR , " bad return from "
" pci_alloc_consistent \n " ) ;
netxen_free_hw_resources ( adapter ) ;
err = - ENOMEM ;
return err ;
}
rcv_desc - > desc_head = ( struct rcv_desc * ) addr ;
2007-01-02 13:39:10 +03:00
adapter - > ctx_desc - > rcv_ctx [ ring ] . rcv_ring_addr =
cpu_to_le64 ( rcv_desc - > phys_addr ) ;
2006-12-04 20:23:25 +03:00
adapter - > ctx_desc - > rcv_ctx [ ring ] . rcv_ring_size =
2007-01-02 13:39:10 +03:00
cpu_to_le32 ( rcv_desc - > max_rx_desc_count ) ;
2008-07-22 06:44:00 +04:00
rcv_desc - > crb_rcv_producer =
recv_crb_registers [ adapter - > portnum ] .
crb_rcv_producer [ ring ] ;
2006-10-21 23:33:03 +04:00
}
2008-07-22 06:44:00 +04:00
addr = pci_alloc_consistent ( adapter - > pdev , STATUS_DESC_RINGSIZE ,
& recv_ctx - > rcv_status_desc_phys_addr ) ;
2006-10-21 23:33:03 +04:00
if ( addr = = NULL ) {
DPRINTK ( ERR , " bad return from "
" pci_alloc_consistent \n " ) ;
netxen_free_hw_resources ( adapter ) ;
err = - ENOMEM ;
return err ;
}
recv_ctx - > rcv_status_desc_head = ( struct status_desc * ) addr ;
2007-01-02 13:39:10 +03:00
adapter - > ctx_desc - > sts_ring_addr =
cpu_to_le64 ( recv_ctx - > rcv_status_desc_phys_addr ) ;
adapter - > ctx_desc - > sts_ring_size =
cpu_to_le32 ( adapter - > max_rx_desc_count ) ;
2008-07-22 06:44:00 +04:00
recv_ctx - > crb_sts_consumer =
recv_crb_registers [ adapter - > portnum ] . crb_sts_consumer ;
2006-10-21 23:33:03 +04:00
}
/* Window = 1 */
2006-12-04 20:23:25 +03:00
writel ( lower32 ( adapter - > ctx_desc_phys_addr ) ,
2007-04-20 18:53:52 +04:00
NETXEN_CRB_NORMALIZE ( adapter , CRB_CTX_ADDR_REG_LO ( func_id ) ) ) ;
2006-12-04 20:23:25 +03:00
writel ( upper32 ( adapter - > ctx_desc_phys_addr ) ,
2007-04-20 18:53:52 +04:00
NETXEN_CRB_NORMALIZE ( adapter , CRB_CTX_ADDR_REG_HI ( func_id ) ) ) ;
writel ( NETXEN_CTX_SIGNATURE | func_id ,
NETXEN_CRB_NORMALIZE ( adapter , CRB_CTX_SIGNATURE_REG ( func_id ) ) ) ;
2006-10-21 23:33:03 +04:00
return err ;
}
void netxen_free_hw_resources ( struct netxen_adapter * adapter )
{
struct netxen_recv_context * recv_ctx ;
struct netxen_rcv_desc_ctx * rcv_desc ;
int ctx , ring ;
2006-12-04 20:23:25 +03:00
if ( adapter - > ctx_desc ! = NULL ) {
2008-07-22 06:44:00 +04:00
pci_free_consistent ( adapter - > pdev ,
2006-12-04 20:23:25 +03:00
sizeof ( struct netxen_ring_ctx ) +
sizeof ( uint32_t ) ,
adapter - > ctx_desc ,
adapter - > ctx_desc_phys_addr ) ;
adapter - > ctx_desc = NULL ;
}
2006-10-21 23:33:03 +04:00
if ( adapter - > ahw . cmd_desc_head ! = NULL ) {
2008-07-22 06:44:00 +04:00
pci_free_consistent ( adapter - > pdev ,
2006-10-21 23:33:03 +04:00
sizeof ( struct cmd_desc_type0 ) *
adapter - > max_tx_desc_count ,
adapter - > ahw . cmd_desc_head ,
adapter - > ahw . cmd_desc_phys_addr ) ;
adapter - > ahw . cmd_desc_head = NULL ;
}
for ( ctx = 0 ; ctx < MAX_RCV_CTX ; + + ctx ) {
recv_ctx = & adapter - > recv_ctx [ ctx ] ;
for ( ring = 0 ; ring < NUM_RCV_DESC_RINGS ; ring + + ) {
rcv_desc = & recv_ctx - > rcv_desc [ ring ] ;
if ( rcv_desc - > desc_head ! = NULL ) {
2008-07-22 06:44:00 +04:00
pci_free_consistent ( adapter - > pdev ,
2006-10-21 23:33:03 +04:00
RCV_DESC_RINGSIZE ,
rcv_desc - > desc_head ,
rcv_desc - > phys_addr ) ;
rcv_desc - > desc_head = NULL ;
}
}
if ( recv_ctx - > rcv_status_desc_head ! = NULL ) {
2008-07-22 06:44:00 +04:00
pci_free_consistent ( adapter - > pdev ,
2006-10-21 23:33:03 +04:00
STATUS_DESC_RINGSIZE ,
recv_ctx - > rcv_status_desc_head ,
recv_ctx - >
rcv_status_desc_phys_addr ) ;
recv_ctx - > rcv_status_desc_head = NULL ;
}
}
}
void netxen_tso_check ( struct netxen_adapter * adapter ,
struct cmd_desc_type0 * desc , struct sk_buff * skb )
{
if ( desc - > mss ) {
2007-03-13 02:09:15 +03:00
desc - > total_hdr_length = ( sizeof ( struct ethhdr ) +
2007-03-19 03:43:48 +03:00
ip_hdrlen ( skb ) + tcp_hdrlen ( skb ) ) ;
2006-12-04 20:23:25 +03:00
netxen_set_cmd_desc_opcode ( desc , TX_TCP_LSO ) ;
2006-12-18 16:51:58 +03:00
} else if ( skb - > ip_summed = = CHECKSUM_PARTIAL ) {
2007-04-21 09:47:35 +04:00
if ( ip_hdr ( skb ) - > protocol = = IPPROTO_TCP ) {
2006-12-04 20:23:25 +03:00
netxen_set_cmd_desc_opcode ( desc , TX_TCP_PKT ) ;
2007-04-21 09:47:35 +04:00
} else if ( ip_hdr ( skb ) - > protocol = = IPPROTO_UDP ) {
2006-12-04 20:23:25 +03:00
netxen_set_cmd_desc_opcode ( desc , TX_UDP_PKT ) ;
2006-10-21 23:33:03 +04:00
} else {
return ;
}
}
2007-04-26 04:55:53 +04:00
desc - > tcp_hdr_offset = skb_transport_offset ( skb ) ;
2007-03-11 04:16:10 +03:00
desc - > ip_hdr_offset = skb_network_offset ( skb ) ;
2006-10-21 23:33:03 +04:00
}
int netxen_is_flash_supported ( struct netxen_adapter * adapter )
{
const int locs [ ] = { 0 , 0x4 , 0x100 , 0x4000 , 0x4128 } ;
int addr , val01 , val02 , i , j ;
/* if the flash size less than 4Mb, make huge war cry and die */
for ( j = 1 ; j < 4 ; j + + ) {
2006-11-29 20:00:10 +03:00
addr = j * NETXEN_NIC_WINDOW_MARGIN ;
2007-09-02 14:30:18 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( locs ) ; i + + ) {
2006-10-21 23:33:03 +04:00
if ( netxen_rom_fast_read ( adapter , locs [ i ] , & val01 ) = = 0
& & netxen_rom_fast_read ( adapter , ( addr + locs [ i ] ) ,
& val02 ) = = 0 ) {
if ( val01 = = val02 )
return - 1 ;
} else
return - 1 ;
}
}
return 0 ;
}
static int netxen_get_flash_block ( struct netxen_adapter * adapter , int base ,
2007-12-22 22:44:00 +03:00
int size , __le32 * buf )
2006-10-21 23:33:03 +04:00
{
int i , addr ;
2007-12-22 22:44:00 +03:00
__le32 * ptr32 ;
u32 v ;
2006-10-21 23:33:03 +04:00
addr = base ;
ptr32 = buf ;
for ( i = 0 ; i < size / sizeof ( u32 ) ; i + + ) {
2007-12-22 22:44:00 +03:00
if ( netxen_rom_fast_read ( adapter , addr , & v ) = = - 1 )
2006-10-21 23:33:03 +04:00
return - 1 ;
2007-12-22 22:44:00 +03:00
* ptr32 = cpu_to_le32 ( v ) ;
2006-10-21 23:33:03 +04:00
ptr32 + + ;
addr + = sizeof ( u32 ) ;
}
if ( ( char * ) buf + size > ( char * ) ptr32 ) {
2007-12-22 22:44:00 +03:00
__le32 local ;
if ( netxen_rom_fast_read ( adapter , addr , & v ) = = - 1 )
2006-10-21 23:33:03 +04:00
return - 1 ;
2007-12-22 22:44:00 +03:00
local = cpu_to_le32 ( v ) ;
2006-10-21 23:33:03 +04:00
memcpy ( ptr32 , & local , ( char * ) buf + size - ( char * ) ptr32 ) ;
}
return 0 ;
}
2007-12-22 22:44:00 +03:00
int netxen_get_flash_mac_addr ( struct netxen_adapter * adapter , __le64 mac [ ] )
2006-10-21 23:33:03 +04:00
{
2007-12-22 22:44:00 +03:00
__le32 * pmac = ( __le32 * ) & mac [ 0 ] ;
2006-10-21 23:33:03 +04:00
if ( netxen_get_flash_block ( adapter ,
2007-06-07 15:36:36 +04:00
NETXEN_USER_START +
2006-10-21 23:33:03 +04:00
offsetof ( struct netxen_new_user_info ,
mac_addr ) ,
FLASH_NUM_PORTS * sizeof ( u64 ) , pmac ) = = - 1 ) {
return - 1 ;
}
2007-12-22 22:44:00 +03:00
if ( * mac = = cpu_to_le64 ( ~ 0ULL ) ) {
2006-10-21 23:33:03 +04:00
if ( netxen_get_flash_block ( adapter ,
2007-06-07 15:36:36 +04:00
NETXEN_USER_START_OLD +
2006-10-21 23:33:03 +04:00
offsetof ( struct netxen_user_old_info ,
mac_addr ) ,
FLASH_NUM_PORTS * sizeof ( u64 ) ,
pmac ) = = - 1 )
return - 1 ;
2007-12-22 22:44:00 +03:00
if ( * mac = = cpu_to_le64 ( ~ 0ULL ) )
2006-10-21 23:33:03 +04:00
return - 1 ;
}
return 0 ;
}
/*
* Changes the CRB window to the specified window .
*/
void netxen_nic_pci_change_crbwindow ( struct netxen_adapter * adapter , u32 wndw )
{
void __iomem * offset ;
u32 tmp ;
int count = 0 ;
if ( adapter - > curr_window = = wndw )
return ;
2007-04-20 18:53:05 +04:00
switch ( adapter - > ahw . pci_func ) {
2007-04-20 18:52:37 +04:00
case 0 :
offset = PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG ( PCIX_CRB_WINDOW ) ) ;
break ;
case 1 :
offset = PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG ( PCIX_CRB_WINDOW_F1 ) ) ;
break ;
case 2 :
offset = PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG ( PCIX_CRB_WINDOW_F2 ) ) ;
break ;
case 3 :
offset = PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG ( PCIX_CRB_WINDOW_F3 ) ) ;
break ;
default :
2007-11-20 04:48:24 +03:00
printk ( KERN_INFO " Changing the window for PCI function "
2007-04-20 18:53:05 +04:00
" %d \n " , adapter - > ahw . pci_func ) ;
2007-04-20 18:52:37 +04:00
offset = PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG ( PCIX_CRB_WINDOW ) ) ;
break ;
}
2006-10-21 23:33:03 +04:00
/*
* Move the CRB window .
* We need to write to the " direct access " region of PCI
* to avoid a race condition where the window register has
* not been successfully written across CRB before the target
* register address is received by PCI . The direct region bypasses
* the CRB bus .
*/
if ( wndw & 0x1 )
wndw = NETXEN_WINDOW_ONE ;
writel ( wndw , offset ) ;
/* MUST make sure window is set before we forge on... */
while ( ( tmp = readl ( offset ) ) ! = wndw ) {
printk ( KERN_WARNING " %s: %s WARNING: CRB window value not "
" registered properly: 0x%08x. \n " ,
netxen_nic_driver_name , __FUNCTION__ , tmp ) ;
mdelay ( 1 ) ;
if ( count > = 10 )
break ;
count + + ;
}
2007-04-20 18:55:26 +04:00
if ( wndw = = NETXEN_WINDOW_ONE )
adapter - > curr_window = 1 ;
else
adapter - > curr_window = 0 ;
2006-10-21 23:33:03 +04:00
}
2007-07-02 08:07:57 +04:00
int netxen_load_firmware ( struct netxen_adapter * adapter )
2006-10-21 23:33:03 +04:00
{
int i ;
2007-02-28 16:16:40 +03:00
u32 data , size = 0 ;
u32 flashaddr = NETXEN_FLASH_BASE , memaddr = NETXEN_PHANTOM_MEM_BASE ;
2006-10-21 23:33:03 +04:00
u64 off ;
void __iomem * addr ;
size = NETXEN_FIRMWARE_LEN ;
writel ( 1 , NETXEN_CRB_NORMALIZE ( adapter , NETXEN_ROMUSB_GLB_CAS_RST ) ) ;
for ( i = 0 ; i < size ; i + + ) {
2007-07-02 08:07:57 +04:00
int retries = 10 ;
if ( netxen_rom_fast_read ( adapter , flashaddr , ( int * ) & data ) ! = 0 )
return - EIO ;
2006-11-29 20:00:10 +03:00
off = netxen_nic_pci_set_window ( adapter , memaddr ) ;
addr = pci_base_offset ( adapter , off ) ;
2006-10-21 23:33:03 +04:00
writel ( data , addr ) ;
2007-07-02 08:07:57 +04:00
do {
if ( readl ( addr ) = = data )
break ;
msleep ( 100 ) ;
writel ( data , addr ) ;
} while ( - - retries ) ;
if ( ! retries ) {
printk ( KERN_ERR " %s: firmware load aborted, write failed at 0x%x \n " ,
netxen_nic_driver_name , memaddr ) ;
return - EIO ;
}
2006-10-21 23:33:03 +04:00
flashaddr + = 4 ;
memaddr + = 4 ;
}
udelay ( 100 ) ;
/* make sure Casper is powered on */
writel ( 0x3fff ,
NETXEN_CRB_NORMALIZE ( adapter , NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL ) ) ;
writel ( 0 , NETXEN_CRB_NORMALIZE ( adapter , NETXEN_ROMUSB_GLB_CAS_RST ) ) ;
2007-07-02 08:07:57 +04:00
return 0 ;
2006-10-21 23:33:03 +04:00
}
int
netxen_nic_hw_write_wx ( struct netxen_adapter * adapter , u64 off , void * data ,
int len )
{
void __iomem * addr ;
if ( ADDR_IN_WINDOW1 ( off ) ) {
addr = NETXEN_CRB_NORMALIZE ( adapter , off ) ;
} else { /* Window 0 */
2006-11-29 20:00:10 +03:00
addr = pci_base_offset ( adapter , off ) ;
2006-10-21 23:33:03 +04:00
netxen_nic_pci_change_crbwindow ( adapter , 0 ) ;
}
DPRINTK ( INFO , " writing to base %lx offset %llx addr %p "
" data %llx len %d \n " ,
2006-11-29 20:00:10 +03:00
pci_base ( adapter , off ) , off , addr ,
2006-10-21 23:33:03 +04:00
* ( unsigned long long * ) data , len ) ;
2006-11-29 20:00:10 +03:00
if ( ! addr ) {
netxen_nic_pci_change_crbwindow ( adapter , 1 ) ;
return 1 ;
}
2006-10-21 23:33:03 +04:00
switch ( len ) {
case 1 :
writeb ( * ( u8 * ) data , addr ) ;
break ;
case 2 :
writew ( * ( u16 * ) data , addr ) ;
break ;
case 4 :
writel ( * ( u32 * ) data , addr ) ;
break ;
case 8 :
writeq ( * ( u64 * ) data , addr ) ;
break ;
default :
DPRINTK ( INFO ,
" writing data %lx to offset %llx, num words=%d \n " ,
* ( unsigned long * ) data , off , ( len > > 3 ) ) ;
netxen_nic_hw_block_write64 ( ( u64 __iomem * ) data , addr ,
( len > > 3 ) ) ;
break ;
}
if ( ! ADDR_IN_WINDOW1 ( off ) )
netxen_nic_pci_change_crbwindow ( adapter , 1 ) ;
return 0 ;
}
int
netxen_nic_hw_read_wx ( struct netxen_adapter * adapter , u64 off , void * data ,
int len )
{
void __iomem * addr ;
if ( ADDR_IN_WINDOW1 ( off ) ) { /* Window 1 */
addr = NETXEN_CRB_NORMALIZE ( adapter , off ) ;
} else { /* Window 0 */
2006-11-29 20:00:10 +03:00
addr = pci_base_offset ( adapter , off ) ;
2006-10-21 23:33:03 +04:00
netxen_nic_pci_change_crbwindow ( adapter , 0 ) ;
}
DPRINTK ( INFO , " reading from base %lx offset %llx addr %p \n " ,
2006-11-29 20:00:10 +03:00
pci_base ( adapter , off ) , off , addr ) ;
if ( ! addr ) {
netxen_nic_pci_change_crbwindow ( adapter , 1 ) ;
return 1 ;
}
2006-10-21 23:33:03 +04:00
switch ( len ) {
case 1 :
* ( u8 * ) data = readb ( addr ) ;
break ;
case 2 :
* ( u16 * ) data = readw ( addr ) ;
break ;
case 4 :
* ( u32 * ) data = readl ( addr ) ;
break ;
case 8 :
* ( u64 * ) data = readq ( addr ) ;
break ;
default :
netxen_nic_hw_block_read64 ( ( u64 __iomem * ) data , addr ,
( len > > 3 ) ) ;
break ;
}
DPRINTK ( INFO , " read %lx \n " , * ( unsigned long * ) data ) ;
if ( ! ADDR_IN_WINDOW1 ( off ) )
netxen_nic_pci_change_crbwindow ( adapter , 1 ) ;
return 0 ;
}
void netxen_nic_reg_write ( struct netxen_adapter * adapter , u64 off , u32 val )
{ /* Only for window 1 */
void __iomem * addr ;
addr = NETXEN_CRB_NORMALIZE ( adapter , off ) ;
DPRINTK ( INFO , " writing to base %lx offset %llx addr %p data %x \n " ,
2006-12-04 20:18:00 +03:00
pci_base ( adapter , off ) , off , addr , val ) ;
2006-10-21 23:33:03 +04:00
writel ( val , addr ) ;
}
int netxen_nic_reg_read ( struct netxen_adapter * adapter , u64 off )
{ /* Only for window 1 */
void __iomem * addr ;
int val ;
addr = NETXEN_CRB_NORMALIZE ( adapter , off ) ;
DPRINTK ( INFO , " reading from base %lx offset %llx addr %p \n " ,
2006-12-04 20:18:00 +03:00
pci_base ( adapter , off ) , off , addr ) ;
2006-10-21 23:33:03 +04:00
val = readl ( addr ) ;
writel ( val , addr ) ;
return val ;
}
/* Change the window to 0, write and change back to window 1. */
void netxen_nic_write_w0 ( struct netxen_adapter * adapter , u32 index , u32 value )
{
void __iomem * addr ;
netxen_nic_pci_change_crbwindow ( adapter , 0 ) ;
2006-12-01 16:36:22 +03:00
addr = pci_base_offset ( adapter , index ) ;
2006-10-21 23:33:03 +04:00
writel ( value , addr ) ;
netxen_nic_pci_change_crbwindow ( adapter , 1 ) ;
}
/* Change the window to 0, read and change back to window 1. */
void netxen_nic_read_w0 ( struct netxen_adapter * adapter , u32 index , u32 * value )
{
void __iomem * addr ;
2006-12-01 16:36:22 +03:00
addr = pci_base_offset ( adapter , index ) ;
2006-10-21 23:33:03 +04:00
netxen_nic_pci_change_crbwindow ( adapter , 0 ) ;
* value = readl ( addr ) ;
netxen_nic_pci_change_crbwindow ( adapter , 1 ) ;
}
2007-11-24 05:23:36 +03:00
static int netxen_pci_set_window_warning_count ;
2006-10-21 23:33:03 +04:00
2007-11-05 20:07:31 +03:00
static unsigned long netxen_nic_pci_set_window ( struct netxen_adapter * adapter ,
unsigned long long addr )
2006-10-21 23:33:03 +04:00
{
static int ddr_mn_window = - 1 ;
static int qdr_sn_window = - 1 ;
int window ;
if ( ADDR_IN_RANGE ( addr , NETXEN_ADDR_DDR_NET , NETXEN_ADDR_DDR_NET_MAX ) ) {
/* DDR network side */
addr - = NETXEN_ADDR_DDR_NET ;
window = ( addr > > 25 ) & 0x3ff ;
if ( ddr_mn_window ! = window ) {
ddr_mn_window = window ;
2006-11-29 20:00:10 +03:00
writel ( window , PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG
2007-08-28 15:53:26 +04:00
( PCIX_MN_WINDOW ( adapter - > ahw . pci_func ) ) ) ) ;
2006-10-21 23:33:03 +04:00
/* MUST make sure window is set before we forge on... */
2006-11-29 20:00:10 +03:00
readl ( PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG
2007-08-28 15:53:26 +04:00
( PCIX_MN_WINDOW ( adapter - > ahw . pci_func ) ) ) ) ;
2006-10-21 23:33:03 +04:00
}
2006-11-29 20:00:10 +03:00
addr - = ( window * NETXEN_WINDOW_ONE ) ;
2006-10-21 23:33:03 +04:00
addr + = NETXEN_PCI_DDR_NET ;
} else if ( ADDR_IN_RANGE ( addr , NETXEN_ADDR_OCM0 , NETXEN_ADDR_OCM0_MAX ) ) {
addr - = NETXEN_ADDR_OCM0 ;
addr + = NETXEN_PCI_OCM0 ;
} else if ( ADDR_IN_RANGE ( addr , NETXEN_ADDR_OCM1 , NETXEN_ADDR_OCM1_MAX ) ) {
addr - = NETXEN_ADDR_OCM1 ;
addr + = NETXEN_PCI_OCM1 ;
} else
if ( ADDR_IN_RANGE
( addr , NETXEN_ADDR_QDR_NET , NETXEN_ADDR_QDR_NET_MAX ) ) {
/* QDR network side */
addr - = NETXEN_ADDR_QDR_NET ;
window = ( addr > > 22 ) & 0x3f ;
if ( qdr_sn_window ! = window ) {
qdr_sn_window = window ;
2006-11-29 20:00:10 +03:00
writel ( ( window < < 22 ) ,
PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG
2007-08-28 15:53:26 +04:00
( PCIX_SN_WINDOW ( adapter - > ahw . pci_func ) ) ) ) ;
2006-10-21 23:33:03 +04:00
/* MUST make sure window is set before we forge on... */
2006-11-29 20:00:10 +03:00
readl ( PCI_OFFSET_SECOND_RANGE ( adapter ,
NETXEN_PCIX_PH_REG
2007-08-28 15:53:26 +04:00
( PCIX_SN_WINDOW ( adapter - > ahw . pci_func ) ) ) ) ;
2006-10-21 23:33:03 +04:00
}
addr - = ( window * 0x400000 ) ;
addr + = NETXEN_PCI_QDR_NET ;
} else {
/*
* peg gdb frequently accesses memory that doesn ' t exist ,
* this limits the chit chat so debugging isn ' t slowed down .
*/
if ( ( netxen_pci_set_window_warning_count + + < 8 )
| | ( netxen_pci_set_window_warning_count % 64 = = 0 ) )
printk ( " %s: Warning:netxen_nic_pci_set_window() "
" Unknown address range! \n " ,
netxen_nic_driver_name ) ;
}
return addr ;
}
2007-11-05 20:07:31 +03:00
#if 0
2007-04-20 18:53:05 +04:00
int
netxen_nic_erase_pxe ( struct netxen_adapter * adapter )
{
2007-06-07 15:36:36 +04:00
if ( netxen_rom_fast_write ( adapter , NETXEN_PXE_START , 0 ) = = - 1 ) {
2007-11-24 05:23:36 +03:00
printk ( KERN_ERR " %s: erase pxe failed \n " ,
2007-04-20 18:53:05 +04:00
netxen_nic_driver_name ) ;
return - 1 ;
}
return 0 ;
}
2007-11-05 20:07:31 +03:00
# endif /* 0 */
2007-04-20 18:53:05 +04:00
2006-10-21 23:33:03 +04:00
int netxen_nic_get_board_info ( struct netxen_adapter * adapter )
{
int rv = 0 ;
2007-06-07 15:36:36 +04:00
int addr = NETXEN_BRDCFG_START ;
2006-10-21 23:33:03 +04:00
struct netxen_board_info * boardinfo ;
int index ;
u32 * ptr32 ;
boardinfo = & adapter - > ahw . boardcfg ;
ptr32 = ( u32 * ) boardinfo ;
for ( index = 0 ; index < sizeof ( struct netxen_board_info ) / sizeof ( u32 ) ;
index + + ) {
if ( netxen_rom_fast_read ( adapter , addr , ptr32 ) = = - 1 ) {
return - EIO ;
}
ptr32 + + ;
addr + = sizeof ( u32 ) ;
}
if ( boardinfo - > magic ! = NETXEN_BDINFO_MAGIC ) {
printk ( " %s: ERROR reading %s board config. "
" Read %x, expected %x \n " , netxen_nic_driver_name ,
netxen_nic_driver_name ,
boardinfo - > magic , NETXEN_BDINFO_MAGIC ) ;
rv = - 1 ;
}
if ( boardinfo - > header_version ! = NETXEN_BDINFO_VERSION ) {
printk ( " %s: Unknown board config version. "
" Read %x, expected %x \n " , netxen_nic_driver_name ,
boardinfo - > header_version , NETXEN_BDINFO_VERSION ) ;
rv = - 1 ;
}
DPRINTK ( INFO , " Discovered board type:0x%x " , boardinfo - > board_type ) ;
switch ( ( netxen_brdtype_t ) boardinfo - > board_type ) {
case NETXEN_BRDTYPE_P2_SB35_4G :
adapter - > ahw . board_type = NETXEN_NIC_GBE ;
break ;
case NETXEN_BRDTYPE_P2_SB31_10G :
case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ :
case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ :
case NETXEN_BRDTYPE_P2_SB31_10G_CX4 :
adapter - > ahw . board_type = NETXEN_NIC_XGBE ;
break ;
case NETXEN_BRDTYPE_P1_BD :
case NETXEN_BRDTYPE_P1_SB :
case NETXEN_BRDTYPE_P1_SMAX :
case NETXEN_BRDTYPE_P1_SOCK :
adapter - > ahw . board_type = NETXEN_NIC_GBE ;
break ;
default :
printk ( " %s: Unknown(%x) \n " , netxen_nic_driver_name ,
boardinfo - > board_type ) ;
break ;
}
return rv ;
}
/* NIU access sections */
2007-04-20 18:52:37 +04:00
int netxen_nic_set_mtu_gb ( struct netxen_adapter * adapter , int new_mtu )
2006-10-21 23:33:03 +04:00
{
netxen_nic_write_w0 ( adapter ,
2008-06-16 09:59:44 +04:00
NETXEN_NIU_GB_MAX_FRAME_SIZE ( adapter - > physical_port ) ,
new_mtu ) ;
2006-10-21 23:33:03 +04:00
return 0 ;
}
2007-04-20 18:52:37 +04:00
int netxen_nic_set_mtu_xgb ( struct netxen_adapter * adapter , int new_mtu )
2006-10-21 23:33:03 +04:00
{
new_mtu + = NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE ;
2008-06-16 09:59:44 +04:00
if ( adapter - > physical_port = = 0 )
2007-11-24 05:23:36 +03:00
netxen_nic_write_w0 ( adapter , NETXEN_NIU_XGE_MAX_FRAME_SIZE ,
2007-04-20 18:53:52 +04:00
new_mtu ) ;
2007-11-24 05:23:36 +03:00
else
2007-04-20 18:53:52 +04:00
netxen_nic_write_w0 ( adapter , NETXEN_NIU_XG1_MAX_FRAME_SIZE ,
new_mtu ) ;
2006-10-21 23:33:03 +04:00
return 0 ;
}
void netxen_nic_init_niu_gb ( struct netxen_adapter * adapter )
{
2008-06-16 09:59:44 +04:00
netxen_niu_gbe_init_port ( adapter , adapter - > physical_port ) ;
2006-10-21 23:33:03 +04:00
}
void
netxen_crb_writelit_adapter ( struct netxen_adapter * adapter , unsigned long off ,
int data )
{
void __iomem * addr ;
if ( ADDR_IN_WINDOW1 ( off ) ) {
writel ( data , NETXEN_CRB_NORMALIZE ( adapter , off ) ) ;
} else {
netxen_nic_pci_change_crbwindow ( adapter , 0 ) ;
2006-12-01 16:36:22 +03:00
addr = pci_base_offset ( adapter , off ) ;
2006-10-21 23:33:03 +04:00
writel ( data , addr ) ;
netxen_nic_pci_change_crbwindow ( adapter , 1 ) ;
}
}
2007-04-20 18:52:37 +04:00
void netxen_nic_set_link_parameters ( struct netxen_adapter * adapter )
2006-10-21 23:33:03 +04:00
{
2007-01-02 13:39:10 +03:00
__u32 status ;
__u32 autoneg ;
__u32 mode ;
2006-10-21 23:33:03 +04:00
netxen_nic_read_w0 ( adapter , NETXEN_NIU_MODE , & mode ) ;
if ( netxen_get_niu_enable_ge ( mode ) ) { /* Gb 10/100/1000 Mbps mode */
2006-12-04 20:18:00 +03:00
if ( adapter - > phy_read
& & adapter - >
2007-04-20 18:53:05 +04:00
phy_read ( adapter ,
2006-10-21 23:33:03 +04:00
NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS ,
& status ) = = 0 ) {
if ( netxen_get_phy_link ( status ) ) {
switch ( netxen_get_phy_speed ( status ) ) {
case 0 :
2007-04-20 18:52:37 +04:00
adapter - > link_speed = SPEED_10 ;
2006-10-21 23:33:03 +04:00
break ;
case 1 :
2007-04-20 18:52:37 +04:00
adapter - > link_speed = SPEED_100 ;
2006-10-21 23:33:03 +04:00
break ;
case 2 :
2007-04-20 18:52:37 +04:00
adapter - > link_speed = SPEED_1000 ;
2006-10-21 23:33:03 +04:00
break ;
default :
2007-04-20 18:52:37 +04:00
adapter - > link_speed = - 1 ;
2006-10-21 23:33:03 +04:00
break ;
}
switch ( netxen_get_phy_duplex ( status ) ) {
case 0 :
2007-04-20 18:52:37 +04:00
adapter - > link_duplex = DUPLEX_HALF ;
2006-10-21 23:33:03 +04:00
break ;
case 1 :
2007-04-20 18:52:37 +04:00
adapter - > link_duplex = DUPLEX_FULL ;
2006-10-21 23:33:03 +04:00
break ;
default :
2007-04-20 18:52:37 +04:00
adapter - > link_duplex = - 1 ;
2006-10-21 23:33:03 +04:00
break ;
}
2006-12-04 20:18:00 +03:00
if ( adapter - > phy_read
& & adapter - >
2007-04-20 18:53:05 +04:00
phy_read ( adapter ,
2006-10-21 23:33:03 +04:00
NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG ,
2006-12-04 20:23:25 +03:00
& autoneg ) ! = 0 )
2007-04-20 18:52:37 +04:00
adapter - > link_autoneg = autoneg ;
2006-10-21 23:33:03 +04:00
} else
goto link_down ;
} else {
link_down :
2007-04-20 18:52:37 +04:00
adapter - > link_speed = - 1 ;
adapter - > link_duplex = - 1 ;
2006-10-21 23:33:03 +04:00
}
}
}
void netxen_nic_flash_print ( struct netxen_adapter * adapter )
{
u32 fw_major = 0 ;
u32 fw_minor = 0 ;
u32 fw_build = 0 ;
2006-11-29 20:00:10 +03:00
char brd_name [ NETXEN_MAX_SHORT_NAME ] ;
2008-04-22 22:48:35 +04:00
char serial_num [ 32 ] ;
int i , addr ;
2007-04-20 18:56:42 +04:00
__le32 * ptr32 ;
2006-10-21 23:33:03 +04:00
struct netxen_board_info * board_info = & ( adapter - > ahw . boardcfg ) ;
2008-06-16 09:59:45 +04:00
adapter - > driver_mismatch = 0 ;
ptr32 = ( u32 * ) & serial_num ;
addr = NETXEN_USER_START +
offsetof ( struct netxen_new_user_info , serial_num ) ;
for ( i = 0 ; i < 8 ; i + + ) {
if ( netxen_rom_fast_read ( adapter , addr , ptr32 ) = = - 1 ) {
printk ( " %s: ERROR reading %s board userarea. \n " ,
netxen_nic_driver_name ,
netxen_nic_driver_name ) ;
adapter - > driver_mismatch = 1 ;
return ;
2006-11-29 20:00:10 +03:00
}
2008-06-16 09:59:45 +04:00
ptr32 + + ;
addr + = sizeof ( u32 ) ;
}
fw_major = readl ( NETXEN_CRB_NORMALIZE ( adapter ,
NETXEN_FW_VERSION_MAJOR ) ) ;
fw_minor = readl ( NETXEN_CRB_NORMALIZE ( adapter ,
NETXEN_FW_VERSION_MINOR ) ) ;
fw_build =
readl ( NETXEN_CRB_NORMALIZE ( adapter , NETXEN_FW_VERSION_SUB ) ) ;
2008-04-22 22:48:35 +04:00
2008-06-16 09:59:45 +04:00
if ( adapter - > portnum = = 0 ) {
2006-11-29 20:00:10 +03:00
get_brd_name_by_type ( board_info - > board_type , brd_name ) ;
printk ( " NetXen %s Board S/N %s Chip id 0x%x \n " ,
2008-06-16 09:59:45 +04:00
brd_name , serial_num , board_info - > chip_id ) ;
printk ( " NetXen Firmware version %d.%d.%d \n " , fw_major ,
fw_minor , fw_build ) ;
2006-10-21 23:33:03 +04:00
}
2008-06-16 09:59:45 +04:00
2006-10-21 23:33:03 +04:00
if ( fw_major ! = _NETXEN_NIC_LINUX_MAJOR ) {
adapter - > driver_mismatch = 1 ;
}
2007-01-22 17:38:05 +03:00
if ( fw_minor ! = _NETXEN_NIC_LINUX_MINOR & &
fw_minor ! = ( _NETXEN_NIC_LINUX_MINOR + 1 ) ) {
2006-10-21 23:33:03 +04:00
adapter - > driver_mismatch = 1 ;
}
2008-06-16 09:59:45 +04:00
if ( adapter - > driver_mismatch ) {
printk ( KERN_ERR " %s: driver and firmware version mismatch \n " ,
adapter - > netdev - > name ) ;
return ;
}
switch ( adapter - > ahw . board_type ) {
case NETXEN_NIC_GBE :
dev_info ( & adapter - > pdev - > dev , " %s: GbE port initialized \n " ,
adapter - > netdev - > name ) ;
break ;
case NETXEN_NIC_XGBE :
dev_info ( & adapter - > pdev - > dev , " %s: XGbE port initialized \n " ,
adapter - > netdev - > name ) ;
break ;
}
2006-10-21 23:33:03 +04:00
}