106b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz#include <linux/kernel.h> 206b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz#include <linux/ide.h> 35a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 438789fda295689689d064c0157bc363b1837b5e6Paul Gortmaker#include <linux/export.h> 56d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan#include <linux/seq_file.h> 606b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 706b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz#include "ide-disk.h" 806b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 906b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczstatic int smart_enable(ide_drive_t *drive) 1006b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz{ 1122aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz struct ide_cmd cmd; 1222aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz struct ide_taskfile *tf = &cmd.tf; 1306b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 1422aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz memset(&cmd, 0, sizeof(cmd)); 1506b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->feature = ATA_SMART_ENABLE; 1606b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->lbam = ATA_SMART_LBAM_PASS; 1706b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->lbah = ATA_SMART_LBAH_PASS; 1806b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->command = ATA_CMD_SMART; 1960f85019c6c8c1aebf3485a313e0da094bc95d07Sergei Shtylyov cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; 2060f85019c6c8c1aebf3485a313e0da094bc95d07Sergei Shtylyov cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; 2122aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz 2222aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz return ide_no_data_taskfile(drive, &cmd); 2306b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz} 2406b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 2506b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczstatic int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) 2606b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz{ 2722aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz struct ide_cmd cmd; 2822aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz struct ide_taskfile *tf = &cmd.tf; 2906b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 3022aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz memset(&cmd, 0, sizeof(cmd)); 3106b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->feature = sub_cmd; 3206b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->nsect = 0x01; 3306b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->lbam = ATA_SMART_LBAM_PASS; 3406b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->lbah = ATA_SMART_LBAH_PASS; 3506b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz tf->command = ATA_CMD_SMART; 3660f85019c6c8c1aebf3485a313e0da094bc95d07Sergei Shtylyov cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; 3760f85019c6c8c1aebf3485a313e0da094bc95d07Sergei Shtylyov cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; 380dfb991c6943c810175376b58d1c29cfe532541bBartlomiej Zolnierkiewicz cmd.protocol = ATA_PROT_PIO; 3939375853d77bea48b7b334daa3698277af8d33f4Bartlomiej Zolnierkiewicz 4022aa4b32a19b1f231d4ce7e9af6354b577a22a35Bartlomiej Zolnierkiewicz return ide_raw_taskfile(drive, &cmd, buf, 1); 4106b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz} 4206b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 436d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int idedisk_cache_proc_show(struct seq_file *m, void *v) 4406b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz{ 456d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan ide_drive_t *drive = (ide_drive_t *) m->private; 4606b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 4706b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz if (drive->dev_flags & IDE_DFLAG_ID_READ) 486d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan seq_printf(m, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2); 4906b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz else 506d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan seq_printf(m, "(none)\n"); 516d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan return 0; 526d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan} 5306b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 546d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int idedisk_cache_proc_open(struct inode *inode, struct file *file) 556d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan{ 56d9dda78bad879595d8c4220a067fc029d6484a16Al Viro return single_open(file, idedisk_cache_proc_show, PDE_DATA(inode)); 5706b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz} 5806b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 596d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic const struct file_operations idedisk_cache_proc_fops = { 606d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .owner = THIS_MODULE, 616d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .open = idedisk_cache_proc_open, 626d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .read = seq_read, 636d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .llseek = seq_lseek, 646d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .release = single_release, 656d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan}; 666d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan 676d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int idedisk_capacity_proc_show(struct seq_file *m, void *v) 6806b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz{ 696d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan ide_drive_t*drive = (ide_drive_t *)m->private; 7006b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 716d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan seq_printf(m, "%llu\n", (long long)ide_gd_capacity(drive)); 726d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan return 0; 736d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan} 7406b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 756d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int idedisk_capacity_proc_open(struct inode *inode, struct file *file) 766d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan{ 77d9dda78bad879595d8c4220a067fc029d6484a16Al Viro return single_open(file, idedisk_capacity_proc_show, PDE_DATA(inode)); 7806b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz} 7906b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 806d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic const struct file_operations idedisk_capacity_proc_fops = { 816d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .owner = THIS_MODULE, 826d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .open = idedisk_capacity_proc_open, 836d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .read = seq_read, 846d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .llseek = seq_lseek, 856d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .release = single_release, 866d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan}; 876d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan 886d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int __idedisk_proc_show(struct seq_file *m, ide_drive_t *drive, u8 sub_cmd) 8906b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz{ 906d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan u8 *buf; 916d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan 926d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan buf = kmalloc(SECTOR_SIZE, GFP_KERNEL); 936d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan if (!buf) 946d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan return -ENOMEM; 9506b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 9639375853d77bea48b7b334daa3698277af8d33f4Bartlomiej Zolnierkiewicz (void)smart_enable(drive); 9739375853d77bea48b7b334daa3698277af8d33f4Bartlomiej Zolnierkiewicz 986d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan if (get_smart_data(drive, buf, sub_cmd) == 0) { 996d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan __le16 *val = (__le16 *)buf; 1006d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan int i; 1016d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan 1026d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan for (i = 0; i < SECTOR_SIZE / 2; i++) { 1036d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan seq_printf(m, "%04x%c", le16_to_cpu(val[i]), 1046d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan (i % 8) == 7 ? '\n' : ' '); 1056d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan } 10606b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz } 1076d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan kfree(buf); 1086d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan return 0; 1096d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan} 11006b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 1116d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int idedisk_sv_proc_show(struct seq_file *m, void *v) 1126d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan{ 1136d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan return __idedisk_proc_show(m, m->private, ATA_SMART_READ_VALUES); 11406b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz} 11506b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 1166d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int idedisk_sv_proc_open(struct inode *inode, struct file *file) 11706b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz{ 118d9dda78bad879595d8c4220a067fc029d6484a16Al Viro return single_open(file, idedisk_sv_proc_show, PDE_DATA(inode)); 11906b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz} 12006b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 1216d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic const struct file_operations idedisk_sv_proc_fops = { 1226d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .owner = THIS_MODULE, 1236d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .open = idedisk_sv_proc_open, 1246d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .read = seq_read, 1256d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .llseek = seq_lseek, 1266d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .release = single_release, 1276d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan}; 1286d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan 1296d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int idedisk_st_proc_show(struct seq_file *m, void *v) 13006b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz{ 1316d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan return __idedisk_proc_show(m, m->private, ATA_SMART_READ_THRESHOLDS); 13206b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz} 13306b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 1346d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic int idedisk_st_proc_open(struct inode *inode, struct file *file) 1356d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan{ 136d9dda78bad879595d8c4220a067fc029d6484a16Al Viro return single_open(file, idedisk_st_proc_show, PDE_DATA(inode)); 1376d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan} 1386d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan 1396d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyanstatic const struct file_operations idedisk_st_proc_fops = { 1406d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .owner = THIS_MODULE, 1416d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .open = idedisk_st_proc_open, 1426d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .read = seq_read, 1436d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .llseek = seq_lseek, 1446d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan .release = single_release, 1456d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan}; 1466d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan 14706b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczide_proc_entry_t ide_disk_proc[] = { 1486d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan { "cache", S_IFREG|S_IRUGO, &idedisk_cache_proc_fops }, 1496d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan { "capacity", S_IFREG|S_IRUGO, &idedisk_capacity_proc_fops }, 1506d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan { "geometry", S_IFREG|S_IRUGO, &ide_geometry_proc_fops }, 1516d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan { "smart_values", S_IFREG|S_IRUSR, &idedisk_sv_proc_fops }, 1526d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan { "smart_thresholds", S_IFREG|S_IRUSR, &idedisk_st_proc_fops }, 1536d703a81ad5fdd102334751ddacb053ecc6ff046Alexey Dobriyan {} 15406b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz}; 15506b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 15606b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczide_devset_rw_field(bios_cyl, bios_cyl); 15706b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczide_devset_rw_field(bios_head, bios_head); 15806b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczide_devset_rw_field(bios_sect, bios_sect); 15906b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczide_devset_rw_field(failures, failures); 16006b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczide_devset_rw_field(lun, lun); 16106b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczide_devset_rw_field(max_failures, max_failures); 16206b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz 16306b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewiczconst struct ide_proc_devset ide_disk_settings[] = { 16406b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(acoustic, 0, 254), 16506b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(address, 0, 2), 16606b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(bios_cyl, 0, 65535), 16706b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(bios_head, 0, 255), 16806b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(bios_sect, 0, 63), 16906b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(failures, 0, 65535), 17006b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(lun, 0, 7), 17106b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(max_failures, 0, 65535), 17206b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(multcount, 0, 16), 17306b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(nowerr, 0, 1), 17406b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz IDE_PROC_DEVSET(wcache, 0, 1), 17571bfc7a7c73eaf1f99e309dba60822ba050e3ec5Hannes Eder { NULL }, 17606b89518fa69fb7243dc98c31f9a9cfa61bfe788Bartlomiej Zolnierkiewicz}; 177