at v4.15-rc5 177 lines 4.8 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2#include <linux/kernel.h> 3#include <linux/ide.h> 4#include <linux/slab.h> 5#include <linux/export.h> 6#include <linux/seq_file.h> 7 8#include "ide-disk.h" 9 10static int smart_enable(ide_drive_t *drive) 11{ 12 struct ide_cmd cmd; 13 struct ide_taskfile *tf = &cmd.tf; 14 15 memset(&cmd, 0, sizeof(cmd)); 16 tf->feature = ATA_SMART_ENABLE; 17 tf->lbam = ATA_SMART_LBAM_PASS; 18 tf->lbah = ATA_SMART_LBAH_PASS; 19 tf->command = ATA_CMD_SMART; 20 cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; 21 cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; 22 23 return ide_no_data_taskfile(drive, &cmd); 24} 25 26static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) 27{ 28 struct ide_cmd cmd; 29 struct ide_taskfile *tf = &cmd.tf; 30 31 memset(&cmd, 0, sizeof(cmd)); 32 tf->feature = sub_cmd; 33 tf->nsect = 0x01; 34 tf->lbam = ATA_SMART_LBAM_PASS; 35 tf->lbah = ATA_SMART_LBAH_PASS; 36 tf->command = ATA_CMD_SMART; 37 cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; 38 cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; 39 cmd.protocol = ATA_PROT_PIO; 40 41 return ide_raw_taskfile(drive, &cmd, buf, 1); 42} 43 44static int idedisk_cache_proc_show(struct seq_file *m, void *v) 45{ 46 ide_drive_t *drive = (ide_drive_t *) m->private; 47 48 if (drive->dev_flags & IDE_DFLAG_ID_READ) 49 seq_printf(m, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2); 50 else 51 seq_printf(m, "(none)\n"); 52 return 0; 53} 54 55static int idedisk_cache_proc_open(struct inode *inode, struct file *file) 56{ 57 return single_open(file, idedisk_cache_proc_show, PDE_DATA(inode)); 58} 59 60static const struct file_operations idedisk_cache_proc_fops = { 61 .owner = THIS_MODULE, 62 .open = idedisk_cache_proc_open, 63 .read = seq_read, 64 .llseek = seq_lseek, 65 .release = single_release, 66}; 67 68static int idedisk_capacity_proc_show(struct seq_file *m, void *v) 69{ 70 ide_drive_t*drive = (ide_drive_t *)m->private; 71 72 seq_printf(m, "%llu\n", (long long)ide_gd_capacity(drive)); 73 return 0; 74} 75 76static int idedisk_capacity_proc_open(struct inode *inode, struct file *file) 77{ 78 return single_open(file, idedisk_capacity_proc_show, PDE_DATA(inode)); 79} 80 81static const struct file_operations idedisk_capacity_proc_fops = { 82 .owner = THIS_MODULE, 83 .open = idedisk_capacity_proc_open, 84 .read = seq_read, 85 .llseek = seq_lseek, 86 .release = single_release, 87}; 88 89static int __idedisk_proc_show(struct seq_file *m, ide_drive_t *drive, u8 sub_cmd) 90{ 91 u8 *buf; 92 93 buf = kmalloc(SECTOR_SIZE, GFP_KERNEL); 94 if (!buf) 95 return -ENOMEM; 96 97 (void)smart_enable(drive); 98 99 if (get_smart_data(drive, buf, sub_cmd) == 0) { 100 __le16 *val = (__le16 *)buf; 101 int i; 102 103 for (i = 0; i < SECTOR_SIZE / 2; i++) { 104 seq_printf(m, "%04x%c", le16_to_cpu(val[i]), 105 (i % 8) == 7 ? '\n' : ' '); 106 } 107 } 108 kfree(buf); 109 return 0; 110} 111 112static int idedisk_sv_proc_show(struct seq_file *m, void *v) 113{ 114 return __idedisk_proc_show(m, m->private, ATA_SMART_READ_VALUES); 115} 116 117static int idedisk_sv_proc_open(struct inode *inode, struct file *file) 118{ 119 return single_open(file, idedisk_sv_proc_show, PDE_DATA(inode)); 120} 121 122static const struct file_operations idedisk_sv_proc_fops = { 123 .owner = THIS_MODULE, 124 .open = idedisk_sv_proc_open, 125 .read = seq_read, 126 .llseek = seq_lseek, 127 .release = single_release, 128}; 129 130static int idedisk_st_proc_show(struct seq_file *m, void *v) 131{ 132 return __idedisk_proc_show(m, m->private, ATA_SMART_READ_THRESHOLDS); 133} 134 135static int idedisk_st_proc_open(struct inode *inode, struct file *file) 136{ 137 return single_open(file, idedisk_st_proc_show, PDE_DATA(inode)); 138} 139 140static const struct file_operations idedisk_st_proc_fops = { 141 .owner = THIS_MODULE, 142 .open = idedisk_st_proc_open, 143 .read = seq_read, 144 .llseek = seq_lseek, 145 .release = single_release, 146}; 147 148ide_proc_entry_t ide_disk_proc[] = { 149 { "cache", S_IFREG|S_IRUGO, &idedisk_cache_proc_fops }, 150 { "capacity", S_IFREG|S_IRUGO, &idedisk_capacity_proc_fops }, 151 { "geometry", S_IFREG|S_IRUGO, &ide_geometry_proc_fops }, 152 { "smart_values", S_IFREG|S_IRUSR, &idedisk_sv_proc_fops }, 153 { "smart_thresholds", S_IFREG|S_IRUSR, &idedisk_st_proc_fops }, 154 {} 155}; 156 157ide_devset_rw_field(bios_cyl, bios_cyl); 158ide_devset_rw_field(bios_head, bios_head); 159ide_devset_rw_field(bios_sect, bios_sect); 160ide_devset_rw_field(failures, failures); 161ide_devset_rw_field(lun, lun); 162ide_devset_rw_field(max_failures, max_failures); 163 164const struct ide_proc_devset ide_disk_settings[] = { 165 IDE_PROC_DEVSET(acoustic, 0, 254), 166 IDE_PROC_DEVSET(address, 0, 2), 167 IDE_PROC_DEVSET(bios_cyl, 0, 65535), 168 IDE_PROC_DEVSET(bios_head, 0, 255), 169 IDE_PROC_DEVSET(bios_sect, 0, 63), 170 IDE_PROC_DEVSET(failures, 0, 65535), 171 IDE_PROC_DEVSET(lun, 0, 7), 172 IDE_PROC_DEVSET(max_failures, 0, 65535), 173 IDE_PROC_DEVSET(multcount, 0, 16), 174 IDE_PROC_DEVSET(nowerr, 0, 1), 175 IDE_PROC_DEVSET(wcache, 0, 1), 176 { NULL }, 177};