2008-10-13 23:39:45 +04:00
# include <linux/kernel.h>
# include <linux/ide.h>
2009-09-02 04:52:57 +04:00
# include <linux/seq_file.h>
2008-10-13 23:39:45 +04:00
# include "ide-disk.h"
static int smart_enable ( ide_drive_t * drive )
{
2009-03-27 14:46:37 +03:00
struct ide_cmd cmd ;
struct ide_taskfile * tf = & cmd . tf ;
2008-10-13 23:39:45 +04:00
2009-03-27 14:46:37 +03:00
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2008-10-13 23:39:45 +04:00
tf - > feature = ATA_SMART_ENABLE ;
tf - > lbam = ATA_SMART_LBAM_PASS ;
tf - > lbah = ATA_SMART_LBAH_PASS ;
tf - > command = ATA_CMD_SMART ;
2009-04-08 16:13:01 +04:00
cmd . valid . out . tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE ;
cmd . valid . in . tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE ;
2009-03-27 14:46:37 +03:00
return ide_no_data_taskfile ( drive , & cmd ) ;
2008-10-13 23:39:45 +04:00
}
static int get_smart_data ( ide_drive_t * drive , u8 * buf , u8 sub_cmd )
{
2009-03-27 14:46:37 +03:00
struct ide_cmd cmd ;
struct ide_taskfile * tf = & cmd . tf ;
2008-10-13 23:39:45 +04:00
2009-03-27 14:46:37 +03:00
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2008-10-13 23:39:45 +04:00
tf - > feature = sub_cmd ;
tf - > nsect = 0x01 ;
tf - > lbam = ATA_SMART_LBAM_PASS ;
tf - > lbah = ATA_SMART_LBAH_PASS ;
tf - > command = ATA_CMD_SMART ;
2009-04-08 16:13:01 +04:00
cmd . valid . out . tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE ;
cmd . valid . in . tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE ;
2009-03-27 14:46:39 +03:00
cmd . protocol = ATA_PROT_PIO ;
2009-03-27 14:46:32 +03:00
2009-03-27 14:46:37 +03:00
return ide_raw_taskfile ( drive , & cmd , buf , 1 ) ;
2008-10-13 23:39:45 +04:00
}
2009-09-02 04:52:57 +04:00
static int idedisk_cache_proc_show ( struct seq_file * m , void * v )
2008-10-13 23:39:45 +04:00
{
2009-09-02 04:52:57 +04:00
ide_drive_t * drive = ( ide_drive_t * ) m - > private ;
2008-10-13 23:39:45 +04:00
if ( drive - > dev_flags & IDE_DFLAG_ID_READ )
2009-09-02 04:52:57 +04:00
seq_printf ( m , " %i \n " , drive - > id [ ATA_ID_BUF_SIZE ] / 2 ) ;
2008-10-13 23:39:45 +04:00
else
2009-09-02 04:52:57 +04:00
seq_printf ( m , " (none) \n " ) ;
return 0 ;
}
2008-10-13 23:39:45 +04:00
2009-09-02 04:52:57 +04:00
static int idedisk_cache_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , idedisk_cache_proc_show , PDE ( inode ) - > data ) ;
2008-10-13 23:39:45 +04:00
}
2009-09-02 04:52:57 +04:00
static const struct file_operations idedisk_cache_proc_fops = {
. owner = THIS_MODULE ,
. open = idedisk_cache_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
static int idedisk_capacity_proc_show ( struct seq_file * m , void * v )
2008-10-13 23:39:45 +04:00
{
2009-09-02 04:52:57 +04:00
ide_drive_t * drive = ( ide_drive_t * ) m - > private ;
2008-10-13 23:39:45 +04:00
2009-09-02 04:52:57 +04:00
seq_printf ( m , " %llu \n " , ( long long ) ide_gd_capacity ( drive ) ) ;
return 0 ;
}
2008-10-13 23:39:45 +04:00
2009-09-02 04:52:57 +04:00
static int idedisk_capacity_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , idedisk_capacity_proc_show , PDE ( inode ) - > data ) ;
2008-10-13 23:39:45 +04:00
}
2009-09-02 04:52:57 +04:00
static const struct file_operations idedisk_capacity_proc_fops = {
. owner = THIS_MODULE ,
. open = idedisk_capacity_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
static int __idedisk_proc_show ( struct seq_file * m , ide_drive_t * drive , u8 sub_cmd )
2008-10-13 23:39:45 +04:00
{
2009-09-02 04:52:57 +04:00
u8 * buf ;
buf = kmalloc ( SECTOR_SIZE , GFP_KERNEL ) ;
if ( ! buf )
return - ENOMEM ;
2008-10-13 23:39:45 +04:00
2009-03-27 14:46:32 +03:00
( void ) smart_enable ( drive ) ;
2009-09-02 04:52:57 +04:00
if ( get_smart_data ( drive , buf , sub_cmd ) = = 0 ) {
__le16 * val = ( __le16 * ) buf ;
int i ;
for ( i = 0 ; i < SECTOR_SIZE / 2 ; i + + ) {
seq_printf ( m , " %04x%c " , le16_to_cpu ( val [ i ] ) ,
( i % 8 ) = = 7 ? ' \n ' : ' ' ) ;
}
2008-10-13 23:39:45 +04:00
}
2009-09-02 04:52:57 +04:00
kfree ( buf ) ;
return 0 ;
}
2008-10-13 23:39:45 +04:00
2009-09-02 04:52:57 +04:00
static int idedisk_sv_proc_show ( struct seq_file * m , void * v )
{
return __idedisk_proc_show ( m , m - > private , ATA_SMART_READ_VALUES ) ;
2008-10-13 23:39:45 +04:00
}
2009-09-02 04:52:57 +04:00
static int idedisk_sv_proc_open ( struct inode * inode , struct file * file )
2008-10-13 23:39:45 +04:00
{
2009-09-02 04:52:57 +04:00
return single_open ( file , idedisk_sv_proc_show , PDE ( inode ) - > data ) ;
2008-10-13 23:39:45 +04:00
}
2009-09-02 04:52:57 +04:00
static const struct file_operations idedisk_sv_proc_fops = {
. owner = THIS_MODULE ,
. open = idedisk_sv_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
static int idedisk_st_proc_show ( struct seq_file * m , void * v )
2008-10-13 23:39:45 +04:00
{
2009-09-02 04:52:57 +04:00
return __idedisk_proc_show ( m , m - > private , ATA_SMART_READ_THRESHOLDS ) ;
2008-10-13 23:39:45 +04:00
}
2009-09-02 04:52:57 +04:00
static int idedisk_st_proc_open ( struct inode * inode , struct file * file )
{
return single_open ( file , idedisk_st_proc_show , PDE ( inode ) - > data ) ;
}
static const struct file_operations idedisk_st_proc_fops = {
. owner = THIS_MODULE ,
. open = idedisk_st_proc_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = single_release ,
} ;
2008-10-13 23:39:45 +04:00
ide_proc_entry_t ide_disk_proc [ ] = {
2009-09-02 04:52:57 +04:00
{ " cache " , S_IFREG | S_IRUGO , & idedisk_cache_proc_fops } ,
{ " capacity " , S_IFREG | S_IRUGO , & idedisk_capacity_proc_fops } ,
{ " geometry " , S_IFREG | S_IRUGO , & ide_geometry_proc_fops } ,
{ " smart_values " , S_IFREG | S_IRUSR , & idedisk_sv_proc_fops } ,
{ " smart_thresholds " , S_IFREG | S_IRUSR , & idedisk_st_proc_fops } ,
{ }
2008-10-13 23:39:45 +04:00
} ;
ide_devset_rw_field ( bios_cyl , bios_cyl ) ;
ide_devset_rw_field ( bios_head , bios_head ) ;
ide_devset_rw_field ( bios_sect , bios_sect ) ;
ide_devset_rw_field ( failures , failures ) ;
ide_devset_rw_field ( lun , lun ) ;
ide_devset_rw_field ( max_failures , max_failures ) ;
const struct ide_proc_devset ide_disk_settings [ ] = {
IDE_PROC_DEVSET ( acoustic , 0 , 254 ) ,
IDE_PROC_DEVSET ( address , 0 , 2 ) ,
IDE_PROC_DEVSET ( bios_cyl , 0 , 65535 ) ,
IDE_PROC_DEVSET ( bios_head , 0 , 255 ) ,
IDE_PROC_DEVSET ( bios_sect , 0 , 63 ) ,
IDE_PROC_DEVSET ( failures , 0 , 65535 ) ,
IDE_PROC_DEVSET ( lun , 0 , 7 ) ,
IDE_PROC_DEVSET ( max_failures , 0 , 65535 ) ,
IDE_PROC_DEVSET ( multcount , 0 , 16 ) ,
IDE_PROC_DEVSET ( nowerr , 0 , 1 ) ,
IDE_PROC_DEVSET ( wcache , 0 , 1 ) ,
2009-03-05 18:10:56 +03:00
{ NULL } ,
2008-10-13 23:39:45 +04:00
} ;