2006-07-12 19:59:32 +04:00
/*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * O . S : Linux
* * FILE NAME : arcmsr_attr . c
2011-01-06 12:32:41 +03:00
* * BY : Nick Cheng
2006-07-12 19:59:32 +04:00
* * Description : attributes exported to sysfs and device host
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * Copyright ( C ) 2002 - 2005 , Areca Technology Corporation All rights reserved
* *
* * Web site : www . areca . com . tw
2007-09-13 13:26:40 +04:00
* * E - mail : support @ areca . com . tw
2006-07-12 19:59:32 +04:00
* *
* * This program is free software ; you can redistribute it and / or modify
* * it under the terms of the GNU General Public License version 2 as
* * published by the Free Software Foundation .
* * 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * Redistribution and use in source and binary forms , with or without
* * modification , are permitted provided that the following conditions
* * are met :
* * 1. Redistributions of source code must retain the above copyright
* * notice , this list of conditions and the following disclaimer .
* * 2. Redistributions in binary form must reproduce the above copyright
* * notice , this list of conditions and the following disclaimer in the
* * documentation and / or other materials provided with the distribution .
* * 3. The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission .
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* * INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* * NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* * DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * For history of changes , see Documentation / scsi / ChangeLog . arcmsr
2020-03-02 11:16:15 +03:00
* * Firmware Specification , see Documentation / scsi / arcmsr_spec . rst
2006-07-12 19:59:32 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/errno.h>
# include <linux/delay.h>
2007-09-13 13:26:40 +04:00
# include <linux/pci.h>
2014-09-24 13:33:34 +04:00
# include <linux/circ_buf.h>
2006-07-12 19:59:32 +04:00
# include <scsi/scsi_cmnd.h>
# include <scsi/scsi_device.h>
# include <scsi/scsi_host.h>
# include <scsi/scsi_transport.h>
# include "arcmsr.h"
2008-02-22 02:13:36 +03:00
struct device_attribute * arcmsr_host_attrs [ ] ;
2006-07-12 19:59:32 +04:00
2010-05-13 05:28:57 +04:00
static ssize_t arcmsr_sysfs_iop_message_read ( struct file * filp ,
struct kobject * kobj ,
2007-09-15 20:41:53 +04:00
struct bin_attribute * bin ,
char * buf , loff_t off ,
size_t count )
2006-07-12 19:59:32 +04:00
{
2008-02-22 02:13:36 +03:00
struct device * dev = container_of ( kobj , struct device , kobj ) ;
struct Scsi_Host * host = class_to_shost ( dev ) ;
2006-07-12 19:59:32 +04:00
struct AdapterControlBlock * acb = ( struct AdapterControlBlock * ) host - > hostdata ;
2014-09-24 13:33:34 +04:00
uint8_t * ptmpQbuffer ;
2006-07-12 19:59:32 +04:00
int32_t allxfer_len = 0 ;
2014-08-19 11:17:45 +04:00
unsigned long flags ;
2006-07-12 19:59:32 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EACCES ;
/* do message unit read. */
ptmpQbuffer = ( uint8_t * ) buf ;
2014-08-19 11:17:45 +04:00
spin_lock_irqsave ( & acb - > rqbuffer_lock , flags ) ;
2014-09-24 13:33:34 +04:00
if ( acb - > rqbuf_getIndex ! = acb - > rqbuf_putIndex ) {
unsigned int tail = acb - > rqbuf_getIndex ;
unsigned int head = acb - > rqbuf_putIndex ;
unsigned int cnt_to_end = CIRC_CNT_TO_END ( head , tail , ARCMSR_MAX_QBUFFER ) ;
allxfer_len = CIRC_CNT ( head , tail , ARCMSR_MAX_QBUFFER ) ;
if ( allxfer_len > ARCMSR_API_DATA_BUFLEN )
allxfer_len = ARCMSR_API_DATA_BUFLEN ;
if ( allxfer_len < = cnt_to_end )
memcpy ( ptmpQbuffer , acb - > rqbuffer + tail , allxfer_len ) ;
else {
memcpy ( ptmpQbuffer , acb - > rqbuffer + tail , cnt_to_end ) ;
memcpy ( ptmpQbuffer + cnt_to_end , acb - > rqbuffer , allxfer_len - cnt_to_end ) ;
2014-08-19 11:17:45 +04:00
}
2014-09-24 13:33:34 +04:00
acb - > rqbuf_getIndex = ( acb - > rqbuf_getIndex + allxfer_len ) % ARCMSR_MAX_QBUFFER ;
2006-07-12 19:59:32 +04:00
}
if ( acb - > acb_flags & ACB_F_IOPDATA_OVERFLOW ) {
2007-10-29 08:08:28 +03:00
struct QBUFFER __iomem * prbuffer ;
2006-07-12 19:59:32 +04:00
acb - > acb_flags & = ~ ACB_F_IOPDATA_OVERFLOW ;
2007-09-13 13:26:40 +04:00
prbuffer = arcmsr_get_iop_rqbuffer ( acb ) ;
2014-08-19 11:17:45 +04:00
if ( arcmsr_Read_iop_rqbuffer_data ( acb , prbuffer ) = = 0 )
acb - > acb_flags | = ACB_F_IOPDATA_OVERFLOW ;
2006-07-12 19:59:32 +04:00
}
2014-08-19 11:17:45 +04:00
spin_unlock_irqrestore ( & acb - > rqbuffer_lock , flags ) ;
return allxfer_len ;
2006-07-12 19:59:32 +04:00
}
2010-05-13 05:28:57 +04:00
static ssize_t arcmsr_sysfs_iop_message_write ( struct file * filp ,
struct kobject * kobj ,
2007-09-15 20:41:53 +04:00
struct bin_attribute * bin ,
char * buf , loff_t off ,
size_t count )
2006-07-12 19:59:32 +04:00
{
2008-02-22 02:13:36 +03:00
struct device * dev = container_of ( kobj , struct device , kobj ) ;
struct Scsi_Host * host = class_to_shost ( dev ) ;
2006-07-12 19:59:32 +04:00
struct AdapterControlBlock * acb = ( struct AdapterControlBlock * ) host - > hostdata ;
2014-09-24 13:33:34 +04:00
int32_t user_len , cnt2end ;
2006-07-12 19:59:32 +04:00
uint8_t * pQbuffer , * ptmpuserbuffer ;
2014-08-19 11:17:45 +04:00
unsigned long flags ;
2006-07-12 19:59:32 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EACCES ;
2014-09-24 13:33:34 +04:00
if ( count > ARCMSR_API_DATA_BUFLEN )
2006-07-12 19:59:32 +04:00
return - EINVAL ;
/* do message unit write. */
ptmpuserbuffer = ( uint8_t * ) buf ;
user_len = ( int32_t ) count ;
2014-08-19 11:17:45 +04:00
spin_lock_irqsave ( & acb - > wqbuffer_lock , flags ) ;
2014-09-24 13:33:34 +04:00
if ( acb - > wqbuf_putIndex ! = acb - > wqbuf_getIndex ) {
2014-08-19 11:17:45 +04:00
arcmsr_write_ioctldata2iop ( acb ) ;
spin_unlock_irqrestore ( & acb - > wqbuffer_lock , flags ) ;
2006-07-12 19:59:32 +04:00
return 0 ; /*need retry*/
} else {
2014-09-24 13:33:34 +04:00
pQbuffer = & acb - > wqbuffer [ acb - > wqbuf_putIndex ] ;
cnt2end = ARCMSR_MAX_QBUFFER - acb - > wqbuf_putIndex ;
if ( user_len > cnt2end ) {
memcpy ( pQbuffer , ptmpuserbuffer , cnt2end ) ;
ptmpuserbuffer + = cnt2end ;
user_len - = cnt2end ;
acb - > wqbuf_putIndex = 0 ;
pQbuffer = acb - > wqbuffer ;
2006-07-12 19:59:32 +04:00
}
2014-09-24 13:33:34 +04:00
memcpy ( pQbuffer , ptmpuserbuffer , user_len ) ;
acb - > wqbuf_putIndex + = user_len ;
acb - > wqbuf_putIndex % = ARCMSR_MAX_QBUFFER ;
if ( acb - > acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED ) {
acb - > acb_flags & =
~ ACB_F_MESSAGE_WQBUFFER_CLEARED ;
arcmsr_write_ioctldata2iop ( acb ) ;
}
spin_unlock_irqrestore ( & acb - > wqbuffer_lock , flags ) ;
return count ;
2006-07-12 19:59:32 +04:00
}
}
2010-05-13 05:28:57 +04:00
static ssize_t arcmsr_sysfs_iop_message_clear ( struct file * filp ,
struct kobject * kobj ,
2007-09-15 20:41:53 +04:00
struct bin_attribute * bin ,
char * buf , loff_t off ,
size_t count )
2006-07-12 19:59:32 +04:00
{
2008-02-22 02:13:36 +03:00
struct device * dev = container_of ( kobj , struct device , kobj ) ;
struct Scsi_Host * host = class_to_shost ( dev ) ;
2006-07-12 19:59:32 +04:00
struct AdapterControlBlock * acb = ( struct AdapterControlBlock * ) host - > hostdata ;
uint8_t * pQbuffer ;
2014-08-19 11:17:45 +04:00
unsigned long flags ;
2006-07-12 19:59:32 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EACCES ;
2014-08-19 11:17:45 +04:00
arcmsr_clear_iop2drv_rqueue_buffer ( acb ) ;
2006-07-12 19:59:32 +04:00
acb - > acb_flags | =
( ACB_F_MESSAGE_WQBUFFER_CLEARED
| ACB_F_MESSAGE_RQBUFFER_CLEARED
| ACB_F_MESSAGE_WQBUFFER_READED ) ;
2014-08-19 11:17:45 +04:00
spin_lock_irqsave ( & acb - > rqbuffer_lock , flags ) ;
2014-09-24 13:33:34 +04:00
acb - > rqbuf_getIndex = 0 ;
acb - > rqbuf_putIndex = 0 ;
2014-08-19 11:17:45 +04:00
spin_unlock_irqrestore ( & acb - > rqbuffer_lock , flags ) ;
spin_lock_irqsave ( & acb - > wqbuffer_lock , flags ) ;
2014-09-24 13:33:34 +04:00
acb - > wqbuf_getIndex = 0 ;
acb - > wqbuf_putIndex = 0 ;
2014-08-19 11:17:45 +04:00
spin_unlock_irqrestore ( & acb - > wqbuffer_lock , flags ) ;
2006-07-12 19:59:32 +04:00
pQbuffer = acb - > rqbuffer ;
memset ( pQbuffer , 0 , sizeof ( struct QBUFFER ) ) ;
pQbuffer = acb - > wqbuffer ;
memset ( pQbuffer , 0 , sizeof ( struct QBUFFER ) ) ;
return 1 ;
}
2017-08-01 17:21:14 +03:00
static const struct bin_attribute arcmsr_sysfs_message_read_attr = {
2006-07-12 19:59:32 +04:00
. attr = {
. name = " mu_read " ,
. mode = S_IRUSR ,
} ,
2014-09-24 13:33:34 +04:00
. size = ARCMSR_API_DATA_BUFLEN ,
2006-07-12 19:59:32 +04:00
. read = arcmsr_sysfs_iop_message_read ,
} ;
2017-08-01 17:21:14 +03:00
static const struct bin_attribute arcmsr_sysfs_message_write_attr = {
2006-07-12 19:59:32 +04:00
. attr = {
. name = " mu_write " ,
. mode = S_IWUSR ,
} ,
2014-09-24 13:33:34 +04:00
. size = ARCMSR_API_DATA_BUFLEN ,
2006-07-12 19:59:32 +04:00
. write = arcmsr_sysfs_iop_message_write ,
} ;
2017-08-01 17:21:14 +03:00
static const struct bin_attribute arcmsr_sysfs_message_clear_attr = {
2006-07-12 19:59:32 +04:00
. attr = {
. name = " mu_clear " ,
. mode = S_IWUSR ,
} ,
. size = 1 ,
. write = arcmsr_sysfs_iop_message_clear ,
} ;
int arcmsr_alloc_sysfs_attr ( struct AdapterControlBlock * acb )
{
struct Scsi_Host * host = acb - > host ;
int error ;
2008-02-22 02:13:36 +03:00
error = sysfs_create_bin_file ( & host - > shost_dev . kobj , & arcmsr_sysfs_message_read_attr ) ;
2006-07-12 19:59:32 +04:00
if ( error ) {
printk ( KERN_ERR " arcmsr: alloc sysfs mu_read failed \n " ) ;
goto error_bin_file_message_read ;
}
2008-02-22 02:13:36 +03:00
error = sysfs_create_bin_file ( & host - > shost_dev . kobj , & arcmsr_sysfs_message_write_attr ) ;
2006-07-12 19:59:32 +04:00
if ( error ) {
printk ( KERN_ERR " arcmsr: alloc sysfs mu_write failed \n " ) ;
goto error_bin_file_message_write ;
}
2008-02-22 02:13:36 +03:00
error = sysfs_create_bin_file ( & host - > shost_dev . kobj , & arcmsr_sysfs_message_clear_attr ) ;
2006-07-12 19:59:32 +04:00
if ( error ) {
printk ( KERN_ERR " arcmsr: alloc sysfs mu_clear failed \n " ) ;
goto error_bin_file_message_clear ;
}
return 0 ;
error_bin_file_message_clear :
2008-02-22 02:13:36 +03:00
sysfs_remove_bin_file ( & host - > shost_dev . kobj , & arcmsr_sysfs_message_write_attr ) ;
2006-07-12 19:59:32 +04:00
error_bin_file_message_write :
2008-02-22 02:13:36 +03:00
sysfs_remove_bin_file ( & host - > shost_dev . kobj , & arcmsr_sysfs_message_read_attr ) ;
2006-07-12 19:59:32 +04:00
error_bin_file_message_read :
return error ;
}
2008-02-22 02:13:36 +03:00
void arcmsr_free_sysfs_attr ( struct AdapterControlBlock * acb )
{
2006-07-12 19:59:32 +04:00
struct Scsi_Host * host = acb - > host ;
2008-02-22 02:13:36 +03:00
sysfs_remove_bin_file ( & host - > shost_dev . kobj , & arcmsr_sysfs_message_clear_attr ) ;
sysfs_remove_bin_file ( & host - > shost_dev . kobj , & arcmsr_sysfs_message_write_attr ) ;
sysfs_remove_bin_file ( & host - > shost_dev . kobj , & arcmsr_sysfs_message_read_attr ) ;
2006-07-12 19:59:32 +04:00
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_driver_version ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %s \n " ,
2006-07-12 19:59:32 +04:00
ARCMSR_DRIVER_VERSION ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_driver_posted_cmd ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %4d \n " ,
2006-07-12 19:59:32 +04:00
atomic_read ( & acb - > ccboutstandingcount ) ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_driver_reset ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %4d \n " ,
2006-07-12 19:59:32 +04:00
acb - > num_resets ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_driver_abort ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %4d \n " ,
2006-07-12 19:59:32 +04:00
acb - > num_aborts ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_fw_model ( struct device * dev , struct device_attribute * attr ,
char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %s \n " ,
2006-07-12 19:59:32 +04:00
acb - > firm_model ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_fw_version ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %s \n " ,
2006-07-12 19:59:32 +04:00
acb - > firm_version ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_fw_request_len ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %4d \n " ,
2006-07-12 19:59:32 +04:00
acb - > firm_request_len ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_fw_numbers_queue ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %4d \n " ,
2006-07-12 19:59:32 +04:00
acb - > firm_numbers_queue ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_fw_sdram_size ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %4d \n " ,
2006-07-12 19:59:32 +04:00
acb - > firm_sdram_size ) ;
}
static ssize_t
2008-02-22 02:13:36 +03:00
arcmsr_attr_host_fw_hd_channels ( struct device * dev ,
struct device_attribute * attr , char * buf )
{
struct Scsi_Host * host = class_to_shost ( dev ) ;
struct AdapterControlBlock * acb =
( struct AdapterControlBlock * ) host - > hostdata ;
2006-07-12 19:59:32 +04:00
return snprintf ( buf , PAGE_SIZE ,
2006-07-29 02:36:46 +04:00
" %4d \n " ,
2006-07-12 19:59:32 +04:00
acb - > firm_hd_channels ) ;
}
2008-02-22 02:13:36 +03:00
static DEVICE_ATTR ( host_driver_version , S_IRUGO , arcmsr_attr_host_driver_version , NULL ) ;
static DEVICE_ATTR ( host_driver_posted_cmd , S_IRUGO , arcmsr_attr_host_driver_posted_cmd , NULL ) ;
static DEVICE_ATTR ( host_driver_reset , S_IRUGO , arcmsr_attr_host_driver_reset , NULL ) ;
static DEVICE_ATTR ( host_driver_abort , S_IRUGO , arcmsr_attr_host_driver_abort , NULL ) ;
static DEVICE_ATTR ( host_fw_model , S_IRUGO , arcmsr_attr_host_fw_model , NULL ) ;
static DEVICE_ATTR ( host_fw_version , S_IRUGO , arcmsr_attr_host_fw_version , NULL ) ;
static DEVICE_ATTR ( host_fw_request_len , S_IRUGO , arcmsr_attr_host_fw_request_len , NULL ) ;
static DEVICE_ATTR ( host_fw_numbers_queue , S_IRUGO , arcmsr_attr_host_fw_numbers_queue , NULL ) ;
static DEVICE_ATTR ( host_fw_sdram_size , S_IRUGO , arcmsr_attr_host_fw_sdram_size , NULL ) ;
static DEVICE_ATTR ( host_fw_hd_channels , S_IRUGO , arcmsr_attr_host_fw_hd_channels , NULL ) ;
struct device_attribute * arcmsr_host_attrs [ ] = {
& dev_attr_host_driver_version ,
& dev_attr_host_driver_posted_cmd ,
& dev_attr_host_driver_reset ,
& dev_attr_host_driver_abort ,
& dev_attr_host_fw_model ,
& dev_attr_host_fw_version ,
& dev_attr_host_fw_request_len ,
& dev_attr_host_fw_numbers_queue ,
& dev_attr_host_fw_sdram_size ,
& dev_attr_host_fw_hd_channels ,
2006-07-12 19:59:32 +04:00
NULL ,
} ;