2006-06-29 12:36:34 -07:00
/* ATM driver model support. */
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/kobject.h>
# include <linux/atmdev.h>
# include "common.h"
# include "resources.h"
# define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev)
2007-12-30 23:16:06 -08:00
static ssize_t show_type ( struct device * cdev ,
struct device_attribute * attr , char * buf )
2006-06-29 12:36:34 -07:00
{
struct atm_dev * adev = to_atm_dev ( cdev ) ;
return sprintf ( buf , " %s \n " , adev - > type ) ;
}
2007-12-30 23:16:06 -08:00
static ssize_t show_address ( struct device * cdev ,
struct device_attribute * attr , char * buf )
2006-06-29 12:36:34 -07:00
{
char * pos = buf ;
struct atm_dev * adev = to_atm_dev ( cdev ) ;
int i ;
for ( i = 0 ; i < ( ESI_LEN - 1 ) ; i + + )
pos + = sprintf ( pos , " %02x: " , adev - > esi [ i ] ) ;
pos + = sprintf ( pos , " %02x \n " , adev - > esi [ i ] ) ;
return pos - buf ;
}
2007-12-30 23:16:06 -08:00
static ssize_t show_atmaddress ( struct device * cdev ,
struct device_attribute * attr , char * buf )
2006-06-29 12:36:34 -07:00
{
2007-02-09 23:24:29 +09:00
unsigned long flags ;
2006-06-29 12:36:34 -07:00
char * pos = buf ;
struct atm_dev * adev = to_atm_dev ( cdev ) ;
2007-02-09 23:24:29 +09:00
struct atm_dev_addr * aaddr ;
2006-06-29 12:36:34 -07:00
int bin [ ] = { 1 , 2 , 10 , 6 , 1 } , * fmt = bin ;
int i , j ;
2007-02-09 23:24:29 +09:00
spin_lock_irqsave ( & adev - > lock , flags ) ;
list_for_each_entry ( aaddr , & adev - > local , entry ) {
2006-06-29 12:36:34 -07:00
for ( i = 0 , j = 0 ; i < ATM_ESA_LEN ; + + i , + + j ) {
if ( j = = * fmt ) {
pos + = sprintf ( pos , " . " ) ;
+ + fmt ;
j = 0 ;
}
pos + = sprintf ( pos , " %02x " , aaddr - > addr . sas_addr . prv [ i ] ) ;
}
pos + = sprintf ( pos , " \n " ) ;
}
2007-02-09 23:24:29 +09:00
spin_unlock_irqrestore ( & adev - > lock , flags ) ;
2006-06-29 12:36:34 -07:00
return pos - buf ;
}
2007-12-30 23:16:06 -08:00
static ssize_t show_carrier ( struct device * cdev ,
struct device_attribute * attr , char * buf )
2006-06-29 12:36:34 -07:00
{
char * pos = buf ;
struct atm_dev * adev = to_atm_dev ( cdev ) ;
pos + = sprintf ( pos , " %d \n " ,
adev - > signal = = ATM_PHY_SIG_LOST ? 0 : 1 ) ;
2007-02-09 23:24:29 +09:00
2006-06-29 12:36:34 -07:00
return pos - buf ;
}
2007-12-30 23:16:06 -08:00
static ssize_t show_link_rate ( struct device * cdev ,
struct device_attribute * attr , char * buf )
2006-06-29 12:36:34 -07:00
{
char * pos = buf ;
struct atm_dev * adev = to_atm_dev ( cdev ) ;
int link_rate ;
/* show the link rate, not the data rate */
switch ( adev - > link_rate ) {
case ATM_OC3_PCR :
link_rate = 155520000 ;
break ;
case ATM_OC12_PCR :
link_rate = 622080000 ;
break ;
case ATM_25_PCR :
link_rate = 25600000 ;
break ;
default :
link_rate = adev - > link_rate * 8 * 53 ;
}
pos + = sprintf ( pos , " %d \n " , link_rate ) ;
2007-02-09 23:24:29 +09:00
2006-06-29 12:36:34 -07:00
return pos - buf ;
}
2007-12-30 23:16:06 -08:00
static DEVICE_ATTR ( address , S_IRUGO , show_address , NULL ) ;
static DEVICE_ATTR ( atmaddress , S_IRUGO , show_atmaddress , NULL ) ;
static DEVICE_ATTR ( carrier , S_IRUGO , show_carrier , NULL ) ;
static DEVICE_ATTR ( type , S_IRUGO , show_type , NULL ) ;
static DEVICE_ATTR ( link_rate , S_IRUGO , show_link_rate , NULL ) ;
static struct device_attribute * atm_attrs [ ] = {
& dev_attr_atmaddress ,
& dev_attr_address ,
& dev_attr_carrier ,
& dev_attr_type ,
& dev_attr_link_rate ,
2006-06-29 12:36:34 -07:00
NULL
} ;
2007-12-30 23:16:06 -08:00
static int atm_uevent ( struct device * cdev , struct kobj_uevent_env * env )
2006-06-29 12:36:34 -07:00
{
struct atm_dev * adev ;
if ( ! cdev )
return - ENODEV ;
adev = to_atm_dev ( cdev ) ;
if ( ! adev )
return - ENODEV ;
2007-08-14 15:15:12 +02:00
if ( add_uevent_var ( env , " NAME=%s%d " , adev - > type , adev - > number ) )
2006-06-29 12:36:34 -07:00
return - ENOMEM ;
return 0 ;
}
2007-12-30 23:16:06 -08:00
static void atm_release ( struct device * cdev )
2006-06-29 12:36:34 -07:00
{
struct atm_dev * adev = to_atm_dev ( cdev ) ;
kfree ( adev ) ;
}
static struct class atm_class = {
. name = " atm " ,
2007-12-30 23:16:06 -08:00
. dev_release = atm_release ,
. dev_uevent = atm_uevent ,
2006-06-29 12:36:34 -07:00
} ;
int atm_register_sysfs ( struct atm_dev * adev )
{
2007-12-30 23:16:06 -08:00
struct device * cdev = & adev - > class_dev ;
2006-10-20 19:48:42 -07:00
int i , j , err ;
2006-06-29 12:36:34 -07:00
cdev - > class = & atm_class ;
2007-12-30 23:16:06 -08:00
dev_set_drvdata ( cdev , adev ) ;
2006-06-29 12:36:34 -07:00
2008-11-10 13:55:14 -08:00
dev_set_name ( cdev , " %s%d " , adev - > type , adev - > number ) ;
2007-12-30 23:16:06 -08:00
err = device_register ( cdev ) ;
2006-06-29 12:36:34 -07:00
if ( err < 0 )
return err ;
2006-10-20 19:48:42 -07:00
for ( i = 0 ; atm_attrs [ i ] ; i + + ) {
2007-12-30 23:16:06 -08:00
err = device_create_file ( cdev , atm_attrs [ i ] ) ;
2006-10-20 19:48:42 -07:00
if ( err )
goto err_out ;
}
2006-06-29 12:36:34 -07:00
return 0 ;
2006-10-20 19:48:42 -07:00
err_out :
for ( j = 0 ; j < i ; j + + )
2007-12-30 23:16:06 -08:00
device_remove_file ( cdev , atm_attrs [ j ] ) ;
device_del ( cdev ) ;
2006-10-20 19:48:42 -07:00
return err ;
2006-06-29 12:36:34 -07:00
}
void atm_unregister_sysfs ( struct atm_dev * adev )
{
2007-12-30 23:16:06 -08:00
struct device * cdev = & adev - > class_dev ;
2006-06-29 12:36:34 -07:00
2007-12-30 23:16:06 -08:00
device_del ( cdev ) ;
2006-06-29 12:36:34 -07:00
}
int __init atm_sysfs_init ( void )
{
return class_register ( & atm_class ) ;
}
void __exit atm_sysfs_exit ( void )
{
class_unregister ( & atm_class ) ;
}