2008-07-18 11:37:13 +08:00
/*
* Copyright ( c ) 2007 Atheros Corporation . All rights reserved .
*
* Derived from Intel e1000 driver
* Copyright ( c ) 1999 - 2005 Intel Corporation . All rights reserved .
*
* 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 .
*
* 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 .
*
* 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 .
*/
# include <linux/netdevice.h>
# include "atl1e.h"
/* This is the only thing that needs to be changed to adjust the
* maximum number of ports that the driver can manage .
*/
# define ATL1E_MAX_NIC 32
# define OPTION_UNSET -1
# define OPTION_DISABLED 0
# define OPTION_ENABLED 1
/* All parameters are treated the same, as an integer array of values.
* This macro just reduces the need to repeat the same declaration code
* over and over ( plus this helps to avoid typo bugs ) .
*/
# define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
# define ATL1E_PARAM(x, desc) \
static int __devinitdata x [ ATL1E_MAX_NIC + 1 ] = ATL1E_PARAM_INIT ; \
2009-02-14 11:14:58 +00:00
static unsigned int num_ # # x ; \
2008-07-18 11:37:13 +08:00
module_param_array_named ( x , x , int , & num_ # # x , 0 ) ; \
MODULE_PARM_DESC ( x , desc ) ;
/* Transmit Memory count
*
* Valid Range : 64 - 2048
*
* Default Value : 128
*/
# define ATL1E_MIN_TX_DESC_CNT 32
# define ATL1E_MAX_TX_DESC_CNT 1020
# define ATL1E_DEFAULT_TX_DESC_CNT 128
ATL1E_PARAM ( tx_desc_cnt , " Transmit description count " ) ;
/* Receive Memory Block Count
*
* Valid Range : 16 - 512
*
* Default Value : 128
*/
# define ATL1E_MIN_RX_MEM_SIZE 8 /* 8KB */
# define ATL1E_MAX_RX_MEM_SIZE 1024 /* 1MB */
# define ATL1E_DEFAULT_RX_MEM_SIZE 256 /* 128KB */
ATL1E_PARAM ( rx_mem_size , " memory size of rx buffer(KB) " ) ;
/* User Specified MediaType Override
*
* Valid Range : 0 - 5
* - 0 - auto - negotiate at all supported speeds
* - 1 - only link at 100 Mbps Full Duplex
* - 2 - only link at 100 Mbps Half Duplex
* - 3 - only link at 10 Mbps Full Duplex
* - 4 - only link at 10 Mbps Half Duplex
* Default Value : 0
*/
ATL1E_PARAM ( media_type , " MediaType Select " ) ;
/* Interrupt Moderate Timer in units of 2 us
*
* Valid Range : 10 - 65535
*
* Default Value : 45000 ( 90 ms )
*/
# define INT_MOD_DEFAULT_CNT 100 /* 200us */
# define INT_MOD_MAX_CNT 65000
# define INT_MOD_MIN_CNT 50
ATL1E_PARAM ( int_mod_timer , " Interrupt Moderator Timer " ) ;
# define AUTONEG_ADV_DEFAULT 0x2F
# define AUTONEG_ADV_MASK 0x2F
# define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
# define FLASH_VENDOR_DEFAULT 0
# define FLASH_VENDOR_MIN 0
# define FLASH_VENDOR_MAX 2
struct atl1e_option {
enum { enable_option , range_option , list_option } type ;
char * name ;
char * err ;
int def ;
union {
struct { /* range_option info */
int min ;
int max ;
} r ;
struct { /* list_option info */
int nr ;
struct atl1e_opt_list { int i ; char * str ; } * p ;
} l ;
} arg ;
} ;
2010-02-09 11:49:48 +00:00
static int __devinit atl1e_validate_option ( int * value , struct atl1e_option * opt , struct atl1e_adapter * adapter )
2008-07-18 11:37:13 +08:00
{
if ( * value = = OPTION_UNSET ) {
* value = opt - > def ;
return 0 ;
}
switch ( opt - > type ) {
case enable_option :
switch ( * value ) {
case OPTION_ENABLED :
2010-02-09 11:49:48 +00:00
netdev_info ( adapter - > netdev ,
" %s Enabled \n " , opt - > name ) ;
2008-07-18 11:37:13 +08:00
return 0 ;
case OPTION_DISABLED :
2010-02-09 11:49:48 +00:00
netdev_info ( adapter - > netdev ,
" %s Disabled \n " , opt - > name ) ;
2008-07-18 11:37:13 +08:00
return 0 ;
}
break ;
case range_option :
if ( * value > = opt - > arg . r . min & & * value < = opt - > arg . r . max ) {
2010-02-09 11:49:48 +00:00
netdev_info ( adapter - > netdev , " %s set to %i \n " ,
opt - > name , * value ) ;
2008-07-18 11:37:13 +08:00
return 0 ;
}
break ;
case list_option : {
int i ;
struct atl1e_opt_list * ent ;
for ( i = 0 ; i < opt - > arg . l . nr ; i + + ) {
ent = & opt - > arg . l . p [ i ] ;
if ( * value = = ent - > i ) {
if ( ent - > str [ 0 ] ! = ' \0 ' )
2010-02-09 11:49:48 +00:00
netdev_info ( adapter - > netdev ,
" %s \n " , ent - > str ) ;
2008-07-18 11:37:13 +08:00
return 0 ;
}
}
break ;
}
default :
BUG ( ) ;
}
2010-02-09 11:49:48 +00:00
netdev_info ( adapter - > netdev , " Invalid %s specified (%i) %s \n " ,
opt - > name , * value , opt - > err ) ;
2008-07-18 11:37:13 +08:00
* value = opt - > def ;
return - 1 ;
}
/*
* atl1e_check_options - Range Checking for Command Line Parameters
* @ adapter : board private structure
*
* This routine checks all command line parameters for valid user
* input . If an invalid value is given , or if no user specified
* value exists , a default value is used . The final value is stored
* in a variable in the adapter structure .
*/
void __devinit atl1e_check_options ( struct atl1e_adapter * adapter )
{
int bd = adapter - > bd_number ;
2010-02-09 11:49:48 +00:00
2008-07-18 11:37:13 +08:00
if ( bd > = ATL1E_MAX_NIC ) {
2010-02-09 11:49:48 +00:00
netdev_notice ( adapter - > netdev ,
" no configuration for board #%i \n " , bd ) ;
netdev_notice ( adapter - > netdev ,
" Using defaults for all values \n " ) ;
2008-07-18 11:37:13 +08:00
}
{ /* Transmit Ring Size */
struct atl1e_option opt = {
. type = range_option ,
. name = " Transmit Ddescription Count " ,
. err = " using default of "
__MODULE_STRING ( ATL1E_DEFAULT_TX_DESC_CNT ) ,
. def = ATL1E_DEFAULT_TX_DESC_CNT ,
. arg = { . r = { . min = ATL1E_MIN_TX_DESC_CNT ,
. max = ATL1E_MAX_TX_DESC_CNT } }
} ;
int val ;
if ( num_tx_desc_cnt > bd ) {
val = tx_desc_cnt [ bd ] ;
2010-02-09 11:49:48 +00:00
atl1e_validate_option ( & val , & opt , adapter ) ;
2008-07-18 11:37:13 +08:00
adapter - > tx_ring . count = ( u16 ) val & 0xFFFC ;
} else
adapter - > tx_ring . count = ( u16 ) opt . def ;
}
{ /* Receive Memory Block Count */
struct atl1e_option opt = {
. type = range_option ,
. name = " Memory size of rx buffer(KB) " ,
. err = " using default of "
__MODULE_STRING ( ATL1E_DEFAULT_RX_MEM_SIZE ) ,
. def = ATL1E_DEFAULT_RX_MEM_SIZE ,
. arg = { . r = { . min = ATL1E_MIN_RX_MEM_SIZE ,
. max = ATL1E_MAX_RX_MEM_SIZE } }
} ;
int val ;
if ( num_rx_mem_size > bd ) {
val = rx_mem_size [ bd ] ;
2010-02-09 11:49:48 +00:00
atl1e_validate_option ( & val , & opt , adapter ) ;
2008-07-18 11:37:13 +08:00
adapter - > rx_ring . page_size = ( u32 ) val * 1024 ;
} else {
adapter - > rx_ring . page_size = ( u32 ) opt . def * 1024 ;
}
}
{ /* Interrupt Moderate Timer */
struct atl1e_option opt = {
. type = range_option ,
. name = " Interrupt Moderate Timer " ,
. err = " using default of "
__MODULE_STRING ( INT_MOD_DEFAULT_CNT ) ,
. def = INT_MOD_DEFAULT_CNT ,
. arg = { . r = { . min = INT_MOD_MIN_CNT ,
. max = INT_MOD_MAX_CNT } }
} ;
int val ;
if ( num_int_mod_timer > bd ) {
val = int_mod_timer [ bd ] ;
2010-02-09 11:49:48 +00:00
atl1e_validate_option ( & val , & opt , adapter ) ;
2008-07-18 11:37:13 +08:00
adapter - > hw . imt = ( u16 ) val ;
} else
adapter - > hw . imt = ( u16 ) ( opt . def ) ;
}
{ /* MediaType */
struct atl1e_option opt = {
. type = range_option ,
. name = " Speed/Duplex Selection " ,
. err = " using default of "
__MODULE_STRING ( MEDIA_TYPE_AUTO_SENSOR ) ,
. def = MEDIA_TYPE_AUTO_SENSOR ,
. arg = { . r = { . min = MEDIA_TYPE_AUTO_SENSOR ,
. max = MEDIA_TYPE_10M_HALF } }
} ;
int val ;
if ( num_media_type > bd ) {
val = media_type [ bd ] ;
2010-02-09 11:49:48 +00:00
atl1e_validate_option ( & val , & opt , adapter ) ;
2008-07-18 11:37:13 +08:00
adapter - > hw . media_type = ( u16 ) val ;
} else
adapter - > hw . media_type = ( u16 ) ( opt . def ) ;
}
}