2005-04-17 02:20:36 +04:00
/*
* Copyright ( C ) 1997 - 1998 Mark Lord
* Copyright ( C ) 2003 Red Hat < alan @ redhat . com >
2007-05-10 02:01:10 +04:00
*
* Some code was moved here from ide . c , see it for original copyrights .
2005-04-17 02:20:36 +04:00
*/
/*
* This is the / proc / ide / filesystem implementation .
*
* Drive / Driver settings can be retrieved by reading the drive ' s
* " settings " files . e . g . " cat /proc/ide0/hda/settings "
* To write a new value " val " into a specific setting " name " , use :
* echo " name:val " > / proc / ide / ide0 / hda / settings
*/
# include <linux/module.h>
# include <asm/uaccess.h>
# include <linux/errno.h>
# include <linux/proc_fs.h>
# include <linux/stat.h>
# include <linux/mm.h>
# include <linux/pci.h>
# include <linux/ctype.h>
# include <linux/ide.h>
# include <linux/seq_file.h>
# include <asm/io.h>
2007-05-10 02:01:11 +04:00
static struct proc_dir_entry * proc_ide_root ;
2005-04-17 02:20:36 +04:00
static int proc_ide_read_imodel
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
ide_hwif_t * hwif = ( ide_hwif_t * ) data ;
int len ;
const char * name ;
switch ( hwif - > chipset ) {
2008-04-26 19:36:40 +04:00
case ide_generic : name = " generic " ; break ;
case ide_pci : name = " pci " ; break ;
case ide_cmd640 : name = " cmd640 " ; break ;
case ide_dtc2278 : name = " dtc2278 " ; break ;
case ide_ali14xx : name = " ali14xx " ; break ;
case ide_qd65xx : name = " qd65xx " ; break ;
case ide_umc8672 : name = " umc8672 " ; break ;
case ide_ht6560b : name = " ht6560b " ; break ;
case ide_rz1000 : name = " rz1000 " ; break ;
case ide_trm290 : name = " trm290 " ; break ;
case ide_cmd646 : name = " cmd646 " ; break ;
case ide_cy82c693 : name = " cy82c693 " ; break ;
case ide_4drives : name = " 4drives " ; break ;
case ide_pmac : name = " mac-io " ; break ;
case ide_au1xxx : name = " au1xxx " ; break ;
case ide_palm3710 : name = " palm3710 " ; break ;
case ide_acorn : name = " acorn " ; break ;
default : name = " (unknown) " ; break ;
2005-04-17 02:20:36 +04:00
}
len = sprintf ( page , " %s \n " , name ) ;
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
static int proc_ide_read_mate
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
ide_hwif_t * hwif = ( ide_hwif_t * ) data ;
int len ;
2008-06-30 22:14:45 +04:00
if ( hwif & & hwif - > mate )
2005-04-17 02:20:36 +04:00
len = sprintf ( page , " %s \n " , hwif - > mate - > name ) ;
else
len = sprintf ( page , " (none) \n " ) ;
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
static int proc_ide_read_channel
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
ide_hwif_t * hwif = ( ide_hwif_t * ) data ;
int len ;
page [ 0 ] = hwif - > channel ? ' 1 ' : ' 0 ' ;
page [ 1 ] = ' \n ' ;
len = 2 ;
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
static int proc_ide_read_identify
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
ide_drive_t * drive = ( ide_drive_t * ) data ;
int len = 0 , i = 0 ;
int err = 0 ;
len = sprintf ( page , " \n " ) ;
if ( drive ) {
2008-07-25 00:53:34 +04:00
__le16 * val = ( __le16 * ) page ;
2005-04-17 02:20:36 +04:00
err = taskfile_lib_get_identify ( drive , page ) ;
if ( ! err ) {
2008-10-11 00:39:28 +04:00
char * out = ( char * ) page + SECTOR_SIZE ;
2005-04-17 02:20:36 +04:00
page = out ;
do {
out + = sprintf ( out , " %04x%c " ,
2008-07-25 00:53:34 +04:00
le16_to_cpup ( val ) , ( + + i & 7 ) ? ' ' : ' \n ' ) ;
2005-04-17 02:20:36 +04:00
val + = 1 ;
2008-10-11 00:39:28 +04:00
} while ( i < SECTOR_SIZE / 2 ) ;
2005-04-17 02:20:36 +04:00
len = out - page ;
}
}
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
2007-05-10 02:01:10 +04:00
/**
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
* ide_find_setting - find a specific setting
* @ st : setting table pointer
2007-05-10 02:01:10 +04:00
* @ name : setting name
*
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
* Scan ' s the setting table for a matching entry and returns
2007-05-10 02:01:10 +04:00
* this or NULL if no entry is found . The caller must hold the
* setting semaphore
*/
2008-10-11 00:39:40 +04:00
static
const struct ide_proc_devset * ide_find_setting ( const struct ide_proc_devset * st ,
char * name )
2007-05-10 02:01:10 +04:00
{
2008-10-11 00:39:40 +04:00
while ( st - > name ) {
if ( strcmp ( st - > name , name ) = = 0 )
2007-05-10 02:01:10 +04:00
break ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
st + + ;
2007-05-10 02:01:10 +04:00
}
2008-10-11 00:39:40 +04:00
return st - > name ? st : NULL ;
2007-05-10 02:01:10 +04:00
}
/**
* ide_read_setting - read an IDE setting
* @ drive : drive to read from
* @ setting : drive setting
*
* Read a drive setting and return the value . The caller
2007-07-10 01:17:56 +04:00
* must hold the ide_setting_mtx when making this call .
2007-05-10 02:01:10 +04:00
*
* BUGS : the data return and error are the same return value
* so an error - EINVAL and true return of the same value cannot
* be told apart
*/
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
static int ide_read_setting ( ide_drive_t * drive ,
2008-10-11 00:39:40 +04:00
const struct ide_proc_devset * setting )
2007-05-10 02:01:10 +04:00
{
2008-10-11 00:39:40 +04:00
const struct ide_devset * ds = setting - > setting ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
int val = - EINVAL ;
2008-10-11 00:39:40 +04:00
if ( ds - > get ) {
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
unsigned long flags ;
2007-05-10 02:01:10 +04:00
spin_lock_irqsave ( & ide_lock , flags ) ;
2008-10-11 00:39:40 +04:00
val = ds - > get ( drive ) ;
2007-05-10 02:01:10 +04:00
spin_unlock_irqrestore ( & ide_lock , flags ) ;
}
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
2007-05-10 02:01:10 +04:00
return val ;
}
/**
* ide_write_setting - read an IDE setting
* @ drive : drive to read from
* @ setting : drive setting
* @ val : value
*
* Write a drive setting if it is possible . The caller
2007-07-10 01:17:56 +04:00
* must hold the ide_setting_mtx when making this call .
2007-05-10 02:01:10 +04:00
*
* BUGS : the data return and error are the same return value
* so an error - EINVAL and true return of the same value cannot
* be told apart
*
* FIXME : This should be changed to enqueue a special request
* to the driver to change settings , and then wait on a sema for completion .
* The current scheme of polling is kludgy , though safe enough .
*/
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
static int ide_write_setting ( ide_drive_t * drive ,
2008-10-11 00:39:40 +04:00
const struct ide_proc_devset * setting , int val )
2007-05-10 02:01:10 +04:00
{
2008-10-11 00:39:40 +04:00
const struct ide_devset * ds = setting - > setting ;
2007-05-10 02:01:10 +04:00
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EACCES ;
2008-10-11 00:39:40 +04:00
if ( ! ds - > set )
2007-05-10 02:01:10 +04:00
return - EPERM ;
2008-10-11 00:39:40 +04:00
if ( ( ds - > flags & DS_SYNC )
& & ( val < setting - > min | | val > setting - > max ) )
2007-05-10 02:01:10 +04:00
return - EINVAL ;
2008-10-11 00:39:40 +04:00
return ide_devset_execute ( drive , ds , val ) ;
2007-05-10 02:01:10 +04:00
}
2008-10-11 00:39:40 +04:00
ide_devset_get ( xfer_rate , current_speed ) ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
2007-05-10 02:01:10 +04:00
static int set_xfer_rate ( ide_drive_t * drive , int arg )
{
2008-01-26 22:13:12 +03:00
ide_task_t task ;
2007-05-10 02:01:10 +04:00
int err ;
2008-07-23 21:55:56 +04:00
if ( arg < XFER_PIO_0 | | arg > XFER_UDMA_6 )
2007-05-10 02:01:10 +04:00
return - EINVAL ;
2008-01-26 22:13:12 +03:00
memset ( & task , 0 , sizeof ( task ) ) ;
2008-10-11 00:39:21 +04:00
task . tf . command = ATA_CMD_SET_FEATURES ;
2008-01-26 22:13:12 +03:00
task . tf . feature = SETFEATURES_XFER ;
task . tf . nsect = ( u8 ) arg ;
task . tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
IDE_TFLAG_IN_NSECT ;
err = ide_no_data_taskfile ( drive , & task ) ;
2007-05-10 02:01:10 +04:00
2008-07-23 21:55:56 +04:00
if ( ! err ) {
2007-05-10 02:01:10 +04:00
ide_set_xfer_rate ( drive , ( u8 ) arg ) ;
ide_driveid_update ( drive ) ;
}
return err ;
}
2008-10-11 00:39:40 +04:00
ide_devset_rw ( current_speed , xfer_rate ) ;
ide_devset_rw_field ( init_speed , init_speed ) ;
ide_devset_rw_field ( nice1 , nice1 ) ;
ide_devset_rw_field ( number , dn ) ;
static const struct ide_proc_devset ide_generic_settings [ ] = {
IDE_PROC_DEVSET ( current_speed , 0 , 70 ) ,
IDE_PROC_DEVSET ( init_speed , 0 , 70 ) ,
IDE_PROC_DEVSET ( io_32bit , 0 , 1 + ( SUPPORT_VLB_SYNC < < 1 ) ) ,
IDE_PROC_DEVSET ( keepsettings , 0 , 1 ) ,
IDE_PROC_DEVSET ( nice1 , 0 , 1 ) ,
IDE_PROC_DEVSET ( number , 0 , 3 ) ,
IDE_PROC_DEVSET ( pio_mode , 0 , 255 ) ,
IDE_PROC_DEVSET ( unmaskirq , 0 , 1 ) ,
IDE_PROC_DEVSET ( using_dma , 0 , 1 ) ,
{ 0 } ,
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
} ;
2007-05-10 02:01:10 +04:00
2005-04-17 02:20:36 +04:00
static void proc_ide_settings_warn ( void )
{
2008-04-26 19:36:40 +04:00
static int warned ;
2005-04-17 02:20:36 +04:00
if ( warned )
return ;
printk ( KERN_WARNING " Warning: /proc/ide/hd?/settings interface is "
" obsolete, and will be removed soon! \n " ) ;
warned = 1 ;
}
static int proc_ide_read_settings
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
2008-10-11 00:39:40 +04:00
const struct ide_proc_devset * setting , * g , * d ;
const struct ide_devset * ds ;
2005-04-17 02:20:36 +04:00
ide_drive_t * drive = ( ide_drive_t * ) data ;
char * out = page ;
int len , rc , mul_factor , div_factor ;
proc_ide_settings_warn ( ) ;
2007-07-10 01:17:56 +04:00
mutex_lock ( & ide_setting_mtx ) ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
g = ide_generic_settings ;
d = drive - > settings ;
2005-04-17 02:20:36 +04:00
out + = sprintf ( out , " name \t \t \t value \t \t min \t \t max \t \t mode \n " ) ;
out + = sprintf ( out , " ---- \t \t \t ----- \t \t --- \t \t --- \t \t ---- \n " ) ;
2008-10-11 00:39:40 +04:00
while ( g - > name | | ( d & & d - > name ) ) {
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
/* read settings in the alphabetical order */
2008-10-11 00:39:40 +04:00
if ( g - > name & & d & & d - > name ) {
if ( strcmp ( d - > name , g - > name ) < 0 )
setting = d + + ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
else
2008-10-11 00:39:40 +04:00
setting = g + + ;
} else if ( d & & d - > name ) {
setting = d + + ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
} else
2008-10-11 00:39:40 +04:00
setting = g + + ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
mul_factor = setting - > mulf ? setting - > mulf ( drive ) : 1 ;
div_factor = setting - > divf ? setting - > divf ( drive ) : 1 ;
2005-04-17 02:20:36 +04:00
out + = sprintf ( out , " %-24s " , setting - > name ) ;
2008-04-26 19:36:40 +04:00
rc = ide_read_setting ( drive , setting ) ;
if ( rc > = 0 )
2005-04-17 02:20:36 +04:00
out + = sprintf ( out , " %-16d " , rc * mul_factor / div_factor ) ;
else
out + = sprintf ( out , " %-16s " , " write-only " ) ;
out + = sprintf ( out , " %-16d%-16d " , ( setting - > min * mul_factor + div_factor - 1 ) / div_factor , setting - > max * mul_factor / div_factor ) ;
2008-10-11 00:39:40 +04:00
ds = setting - > setting ;
if ( ds - > get )
2005-04-17 02:20:36 +04:00
out + = sprintf ( out , " r " ) ;
2008-10-11 00:39:40 +04:00
if ( ds - > set )
2005-04-17 02:20:36 +04:00
out + = sprintf ( out , " w " ) ;
out + = sprintf ( out , " \n " ) ;
}
len = out - page ;
2007-07-10 01:17:56 +04:00
mutex_unlock ( & ide_setting_mtx ) ;
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
# define MAX_LEN 30
static int proc_ide_write_settings ( struct file * file , const char __user * buffer ,
unsigned long count , void * data )
{
ide_drive_t * drive = ( ide_drive_t * ) data ;
char name [ MAX_LEN + 1 ] ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
int for_real = 0 , mul_factor , div_factor ;
2005-04-17 02:20:36 +04:00
unsigned long n ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
2008-10-11 00:39:40 +04:00
const struct ide_proc_devset * setting ;
2005-04-17 02:20:36 +04:00
char * buf , * s ;
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EACCES ;
proc_ide_settings_warn ( ) ;
if ( count > = PAGE_SIZE )
return - EINVAL ;
s = buf = ( char * ) __get_free_page ( GFP_USER ) ;
if ( ! buf )
return - ENOMEM ;
if ( copy_from_user ( buf , buffer , count ) ) {
free_page ( ( unsigned long ) buf ) ;
return - EFAULT ;
}
buf [ count ] = ' \0 ' ;
/*
* Skip over leading whitespace
*/
while ( count & & isspace ( * s ) ) {
- - count ;
+ + s ;
}
/*
* Do one full pass to verify all parameters ,
* then do another to actually write the new settings .
*/
do {
char * p = s ;
n = count ;
while ( n > 0 ) {
unsigned val ;
char * q = p ;
while ( n > 0 & & * p ! = ' : ' ) {
- - n ;
p + + ;
}
if ( * p ! = ' : ' )
goto parse_error ;
if ( p - q > MAX_LEN )
goto parse_error ;
memcpy ( name , q , p - q ) ;
name [ p - q ] = 0 ;
if ( n > 0 ) {
- - n ;
p + + ;
} else
goto parse_error ;
val = simple_strtoul ( p , & q , 10 ) ;
n - = q - p ;
p = q ;
if ( n > 0 & & ! isspace ( * p ) )
goto parse_error ;
while ( n > 0 & & isspace ( * p ) ) {
- - n ;
+ + p ;
}
2007-07-10 01:17:56 +04:00
mutex_lock ( & ide_setting_mtx ) ;
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
/* generic settings first, then driver specific ones */
setting = ide_find_setting ( ide_generic_settings , name ) ;
2008-04-26 19:36:40 +04:00
if ( ! setting ) {
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
if ( drive - > settings )
setting = ide_find_setting ( drive - > settings , name ) ;
if ( ! setting ) {
mutex_unlock ( & ide_setting_mtx ) ;
goto parse_error ;
}
}
if ( for_real ) {
mul_factor = setting - > mulf ? setting - > mulf ( drive ) : 1 ;
div_factor = setting - > divf ? setting - > divf ( drive ) : 1 ;
ide_write_setting ( drive , setting , val * div_factor / mul_factor ) ;
2005-04-17 02:20:36 +04:00
}
2007-07-10 01:17:56 +04:00
mutex_unlock ( & ide_setting_mtx ) ;
2005-04-17 02:20:36 +04:00
}
} while ( ! for_real + + ) ;
free_page ( ( unsigned long ) buf ) ;
return count ;
parse_error :
free_page ( ( unsigned long ) buf ) ;
printk ( " proc_ide_write_settings(): parse error \n " ) ;
return - EINVAL ;
}
int proc_ide_read_capacity
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
2008-04-26 19:36:40 +04:00
int len = sprintf ( page , " %llu \n " , ( long long ) 0x7fffffff ) ;
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL_GPL ( proc_ide_read_capacity ) ;
int proc_ide_read_geometry
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
ide_drive_t * drive = ( ide_drive_t * ) data ;
char * out = page ;
int len ;
2008-04-26 19:36:40 +04:00
out + = sprintf ( out , " physical %d/%d/%d \n " ,
2005-04-17 02:20:36 +04:00
drive - > cyl , drive - > head , drive - > sect ) ;
2008-04-26 19:36:40 +04:00
out + = sprintf ( out , " logical %d/%d/%d \n " ,
2005-04-17 02:20:36 +04:00
drive - > bios_cyl , drive - > bios_head , drive - > bios_sect ) ;
len = out - page ;
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
EXPORT_SYMBOL ( proc_ide_read_geometry ) ;
static int proc_ide_read_dmodel
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
ide_drive_t * drive = ( ide_drive_t * ) data ;
2008-10-11 00:39:19 +04:00
char * m = ( char * ) & drive - > id [ ATA_ID_PROD ] ;
2005-04-17 02:20:36 +04:00
int len ;
2008-10-11 00:39:19 +04:00
len = sprintf ( page , " %.40s \n " , m [ 0 ] ? m : " (none) " ) ;
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
static int proc_ide_read_driver
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
ide_drive_t * drive = ( ide_drive_t * ) data ;
2005-05-26 16:55:34 +04:00
struct device * dev = & drive - > gendev ;
ide_driver_t * ide_drv ;
2005-04-17 02:20:36 +04:00
int len ;
2005-05-26 16:55:34 +04:00
if ( dev - > driver ) {
ide_drv = container_of ( dev - > driver , ide_driver_t , gen_driver ) ;
2005-04-17 02:20:36 +04:00
len = sprintf ( page , " %s version %s \n " ,
2005-05-26 16:55:34 +04:00
dev - > driver - > name , ide_drv - > version ) ;
2005-04-17 02:20:36 +04:00
} else
len = sprintf ( page , " ide-default version 0.9.newide \n " ) ;
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
2005-05-26 16:55:34 +04:00
static int ide_replace_subdriver ( ide_drive_t * drive , const char * driver )
{
struct device * dev = & drive - > gendev ;
int ret = 1 ;
2006-10-03 12:14:23 +04:00
int err ;
2005-05-26 16:55:34 +04:00
device_release_driver ( dev ) ;
/* FIXME: device can still be in use by previous driver */
strlcpy ( drive - > driver_req , driver , sizeof ( drive - > driver_req ) ) ;
2006-10-03 12:14:23 +04:00
err = device_attach ( dev ) ;
if ( err < 0 )
printk ( KERN_WARNING " IDE: %s: device_attach error: %d \n " ,
2008-04-27 00:25:20 +04:00
__func__ , err ) ;
2005-05-26 16:55:34 +04:00
drive - > driver_req [ 0 ] = 0 ;
2006-10-03 12:14:23 +04:00
if ( dev - > driver = = NULL ) {
err = device_attach ( dev ) ;
if ( err < 0 )
printk ( KERN_WARNING
" IDE: %s: device_attach(2) error: %d \n " ,
2008-04-27 00:25:20 +04:00
__func__ , err ) ;
2006-10-03 12:14:23 +04:00
}
2005-05-26 16:55:34 +04:00
if ( dev - > driver & & ! strcmp ( dev - > driver - > name , driver ) )
ret = 0 ;
return ret ;
}
2005-04-17 02:20:36 +04:00
static int proc_ide_write_driver
( struct file * file , const char __user * buffer , unsigned long count , void * data )
{
ide_drive_t * drive = ( ide_drive_t * ) data ;
char name [ 32 ] ;
if ( ! capable ( CAP_SYS_ADMIN ) )
return - EACCES ;
if ( count > 31 )
count = 31 ;
if ( copy_from_user ( name , buffer , count ) )
return - EFAULT ;
name [ count ] = ' \0 ' ;
if ( ide_replace_subdriver ( drive , name ) )
return - EINVAL ;
return count ;
}
static int proc_ide_read_media
( char * page , char * * start , off_t off , int count , int * eof , void * data )
{
ide_drive_t * drive = ( ide_drive_t * ) data ;
const char * media ;
int len ;
switch ( drive - > media ) {
2008-04-26 19:36:40 +04:00
case ide_disk : media = " disk \n " ; break ;
case ide_cdrom : media = " cdrom \n " ; break ;
case ide_tape : media = " tape \n " ; break ;
case ide_floppy : media = " floppy \n " ; break ;
case ide_optical : media = " optical \n " ; break ;
default : media = " UNKNOWN \n " ; break ;
2005-04-17 02:20:36 +04:00
}
2008-04-26 19:36:40 +04:00
strcpy ( page , media ) ;
2005-04-17 02:20:36 +04:00
len = strlen ( media ) ;
2008-04-26 19:36:40 +04:00
PROC_IDE_READ_RETURN ( page , start , off , count , eof , len ) ;
2005-04-17 02:20:36 +04:00
}
static ide_proc_entry_t generic_drive_entries [ ] = {
2008-04-26 19:36:40 +04:00
{ " driver " , S_IFREG | S_IRUGO , proc_ide_read_driver ,
proc_ide_write_driver } ,
{ " identify " , S_IFREG | S_IRUSR , proc_ide_read_identify , NULL } ,
{ " media " , S_IFREG | S_IRUGO , proc_ide_read_media , NULL } ,
{ " model " , S_IFREG | S_IRUGO , proc_ide_read_dmodel , NULL } ,
{ " settings " , S_IFREG | S_IRUSR | S_IWUSR , proc_ide_read_settings ,
proc_ide_write_settings } ,
2005-04-17 02:20:36 +04:00
{ NULL , 0 , NULL , NULL }
} ;
2007-05-10 02:01:10 +04:00
static void ide_add_proc_entries ( struct proc_dir_entry * dir , ide_proc_entry_t * p , void * data )
2005-04-17 02:20:36 +04:00
{
struct proc_dir_entry * ent ;
if ( ! dir | | ! p )
return ;
while ( p - > name ! = NULL ) {
ent = create_proc_entry ( p - > name , p - > mode , dir ) ;
if ( ! ent ) return ;
ent - > data = data ;
ent - > read_proc = p - > read_proc ;
ent - > write_proc = p - > write_proc ;
p + + ;
}
}
2007-05-10 02:01:10 +04:00
static void ide_remove_proc_entries ( struct proc_dir_entry * dir , ide_proc_entry_t * p )
2005-04-17 02:20:36 +04:00
{
if ( ! dir | | ! p )
return ;
while ( p - > name ! = NULL ) {
remove_proc_entry ( p - > name , dir ) ;
p + + ;
}
}
2007-05-10 02:01:10 +04:00
void ide_proc_register_driver ( ide_drive_t * drive , ide_driver_t * driver )
{
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
mutex_lock ( & ide_setting_mtx ) ;
drive - > settings = driver - > settings ;
mutex_unlock ( & ide_setting_mtx ) ;
2007-05-10 02:01:10 +04:00
ide_add_proc_entries ( drive - > proc , driver - > proc , drive ) ;
}
EXPORT_SYMBOL ( ide_proc_register_driver ) ;
/**
* ide_proc_unregister_driver - remove driver specific data
* @ drive : drive
* @ driver : driver
*
* Clean up the driver specific / proc files and IDE settings
* for a given drive .
*
2007-07-10 01:17:56 +04:00
* Takes ide_setting_mtx and ide_lock .
2007-05-10 02:01:10 +04:00
* Caller must hold none of the locks .
*/
void ide_proc_unregister_driver ( ide_drive_t * drive , ide_driver_t * driver )
{
unsigned long flags ;
ide_remove_proc_entries ( drive - > proc , driver - > proc ) ;
2007-07-10 01:17:56 +04:00
mutex_lock ( & ide_setting_mtx ) ;
2007-05-10 02:01:10 +04:00
spin_lock_irqsave ( & ide_lock , flags ) ;
/*
2007-07-10 01:17:56 +04:00
* ide_setting_mtx protects the settings list
2007-05-10 02:01:10 +04:00
* ide_lock protects the use of settings
*
* so we need to hold both , ide_settings_sem because we want to
* modify the settings list , and ide_lock because we cannot take
* a setting out that is being used .
*
* OTOH both ide_ { read , write } _setting are only ever used under
2007-07-10 01:17:56 +04:00
* ide_setting_mtx .
2007-05-10 02:01:10 +04:00
*/
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros.
* Add 'const struct ide_devset **settings' to ide_driver_t.
* Use 'const struct ide_devset **settings' in ide_drive_t instead of
'struct ide_settings_s *settings'. Then convert core code and device
drivers to use struct ide_devset and co.:
- device settings are no longer allocated dynamically for each device
but instead there is an unique struct ide_devset instance per setting
- device driver keeps the pointer to the table of pointers to its
settings in ide_driver_t.settings
- generic settings are kept in ide_generic_setting[]
- ide_proc_[un]register_driver(), ide_find_setting_by_name(),
ide_{read,write}_setting() and proc_ide_{read,write}_settings()
are updated accordingly
- ide*_add_settings() are removed
* Remove no longer used __ide_add_setting(), ide_add_setting(),
__ide_remove_setting() and auto_remove_settings().
* Remove no longer used TYPE_*, SETTING_*, ide_procset_t
and ide_settings_t.
* ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap,
->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields
can now be bitfield flags.
While at it:
* Rename ide_find_setting_by_name() to ide_find_setting().
* Rename write_wcache() to set_wcache().
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
2008-10-11 00:39:28 +04:00
drive - > settings = NULL ;
2007-05-10 02:01:10 +04:00
spin_unlock_irqrestore ( & ide_lock , flags ) ;
2007-07-10 01:17:56 +04:00
mutex_unlock ( & ide_setting_mtx ) ;
2007-05-10 02:01:10 +04:00
}
EXPORT_SYMBOL ( ide_proc_unregister_driver ) ;
2008-02-02 21:56:43 +03:00
void ide_proc_port_register_devices ( ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
int d ;
struct proc_dir_entry * ent ;
struct proc_dir_entry * parent = hwif - > proc ;
char name [ 64 ] ;
for ( d = 0 ; d < MAX_DRIVES ; d + + ) {
ide_drive_t * drive = & hwif - > drives [ d ] ;
if ( ! drive - > present )
continue ;
if ( drive - > proc )
continue ;
drive - > proc = proc_mkdir ( drive - > name , parent ) ;
if ( drive - > proc )
ide_add_proc_entries ( drive - > proc , generic_drive_entries , drive ) ;
2008-04-26 19:36:40 +04:00
sprintf ( name , " ide%d/%s " , ( drive - > name [ 2 ] - ' a ' ) / 2 , drive - > name ) ;
2005-04-17 02:20:36 +04:00
ent = proc_symlink ( drive - > name , proc_ide_root , name ) ;
if ( ! ent ) return ;
}
}
2008-04-18 02:46:22 +04:00
void ide_proc_unregister_device ( ide_drive_t * drive )
2005-04-17 02:20:36 +04:00
{
if ( drive - > proc ) {
ide_remove_proc_entries ( drive - > proc , generic_drive_entries ) ;
remove_proc_entry ( drive - > name , proc_ide_root ) ;
2008-04-18 02:46:22 +04:00
remove_proc_entry ( drive - > name , drive - > hwif - > proc ) ;
2005-04-17 02:20:36 +04:00
drive - > proc = NULL ;
}
}
static ide_proc_entry_t hwif_entries [ ] = {
{ " channel " , S_IFREG | S_IRUGO , proc_ide_read_channel , NULL } ,
{ " mate " , S_IFREG | S_IRUGO , proc_ide_read_mate , NULL } ,
{ " model " , S_IFREG | S_IRUGO , proc_ide_read_imodel , NULL } ,
{ NULL , 0 , NULL , NULL }
} ;
2007-05-10 02:01:11 +04:00
void ide_proc_register_port ( ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
2007-05-10 02:01:11 +04:00
if ( ! hwif - > proc ) {
hwif - > proc = proc_mkdir ( hwif - > name , proc_ide_root ) ;
2005-04-17 02:20:36 +04:00
2007-05-10 02:01:11 +04:00
if ( ! hwif - > proc )
return ;
ide_add_proc_entries ( hwif - > proc , hwif_entries , hwif ) ;
2005-04-17 02:20:36 +04:00
}
}
2007-05-10 02:01:11 +04:00
void ide_proc_unregister_port ( ide_hwif_t * hwif )
2005-04-17 02:20:36 +04:00
{
if ( hwif - > proc ) {
ide_remove_proc_entries ( hwif - > proc , hwif_entries ) ;
remove_proc_entry ( hwif - > name , proc_ide_root ) ;
hwif - > proc = NULL ;
}
}
2005-05-26 16:55:34 +04:00
static int proc_print_driver ( struct device_driver * drv , void * data )
{
ide_driver_t * ide_drv = container_of ( drv , ide_driver_t , gen_driver ) ;
struct seq_file * s = data ;
seq_printf ( s , " %s version %s \n " , drv - > name , ide_drv - > version ) ;
return 0 ;
}
static int ide_drivers_show ( struct seq_file * s , void * p )
{
2006-10-03 12:14:23 +04:00
int err ;
err = bus_for_each_drv ( & ide_bus_type , NULL , s , proc_print_driver ) ;
if ( err < 0 )
printk ( KERN_WARNING " IDE: %s: bus_for_each_drv error: %d \n " ,
2008-04-27 00:25:20 +04:00
__func__ , err ) ;
2005-05-26 16:55:34 +04:00
return 0 ;
}
2005-04-17 02:20:36 +04:00
static int ide_drivers_open ( struct inode * inode , struct file * file )
{
2005-05-26 16:55:34 +04:00
return single_open ( file , & ide_drivers_show , NULL ) ;
2005-04-17 02:20:36 +04:00
}
2005-05-26 16:55:34 +04:00
2007-02-12 11:55:32 +03:00
static const struct file_operations ide_drivers_operations = {
2008-04-29 12:02:35 +04:00
. owner = THIS_MODULE ,
2005-04-17 02:20:36 +04:00
. open = ide_drivers_open ,
. read = seq_read ,
. llseek = seq_lseek ,
2005-05-26 16:55:34 +04:00
. release = single_release ,
2005-04-17 02:20:36 +04:00
} ;
void proc_ide_create ( void )
{
2007-05-10 02:01:11 +04:00
proc_ide_root = proc_mkdir ( " ide " , NULL ) ;
2005-04-17 02:20:36 +04:00
if ( ! proc_ide_root )
return ;
2008-04-29 12:02:35 +04:00
proc_create ( " drivers " , 0 , proc_ide_root , & ide_drivers_operations ) ;
2005-04-17 02:20:36 +04:00
}
void proc_ide_destroy ( void )
{
2005-05-17 08:53:11 +04:00
remove_proc_entry ( " drivers " , proc_ide_root ) ;
2005-04-17 02:20:36 +04:00
remove_proc_entry ( " ide " , NULL ) ;
}