^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/ide.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "ide-disk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) static int smart_enable(ide_drive_t *drive)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) struct ide_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct ide_taskfile *tf = &cmd.tf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) memset(&cmd, 0, sizeof(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) tf->feature = ATA_SMART_ENABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) tf->lbam = ATA_SMART_LBAM_PASS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) tf->lbah = ATA_SMART_LBAH_PASS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) tf->command = ATA_CMD_SMART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return ide_no_data_taskfile(drive, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct ide_cmd cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct ide_taskfile *tf = &cmd.tf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) memset(&cmd, 0, sizeof(cmd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) tf->feature = sub_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) tf->nsect = 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) tf->lbam = ATA_SMART_LBAM_PASS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) tf->lbah = ATA_SMART_LBAH_PASS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) tf->command = ATA_CMD_SMART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) cmd.protocol = ATA_PROT_PIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return ide_raw_taskfile(drive, &cmd, buf, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static int idedisk_cache_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) ide_drive_t *drive = (ide_drive_t *) m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (drive->dev_flags & IDE_DFLAG_ID_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) seq_printf(m, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) seq_printf(m, "(none)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static int idedisk_capacity_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) ide_drive_t*drive = (ide_drive_t *)m->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) seq_printf(m, "%llu\n", (long long)ide_gd_capacity(drive));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int __idedisk_proc_show(struct seq_file *m, ide_drive_t *drive, u8 sub_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u8 *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) buf = kmalloc(SECTOR_SIZE, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) (void)smart_enable(drive);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (get_smart_data(drive, buf, sub_cmd) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) __le16 *val = (__le16 *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) for (i = 0; i < SECTOR_SIZE / 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) seq_printf(m, "%04x%c", le16_to_cpu(val[i]),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) (i % 8) == 7 ? '\n' : ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static int idedisk_sv_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return __idedisk_proc_show(m, m->private, ATA_SMART_READ_VALUES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int idedisk_st_proc_show(struct seq_file *m, void *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return __idedisk_proc_show(m, m->private, ATA_SMART_READ_THRESHOLDS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ide_proc_entry_t ide_disk_proc[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { "cache", S_IFREG|S_IRUGO, idedisk_cache_proc_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { "capacity", S_IFREG|S_IRUGO, idedisk_capacity_proc_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { "geometry", S_IFREG|S_IRUGO, ide_geometry_proc_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { "smart_values", S_IFREG|S_IRUSR, idedisk_sv_proc_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { "smart_thresholds", S_IFREG|S_IRUSR, idedisk_st_proc_show },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) ide_devset_rw_field(bios_cyl, bios_cyl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) ide_devset_rw_field(bios_head, bios_head);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) ide_devset_rw_field(bios_sect, bios_sect);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) ide_devset_rw_field(failures, failures);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ide_devset_rw_field(lun, lun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ide_devset_rw_field(max_failures, max_failures);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) const struct ide_proc_devset ide_disk_settings[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) IDE_PROC_DEVSET(acoustic, 0, 254),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) IDE_PROC_DEVSET(address, 0, 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) IDE_PROC_DEVSET(bios_cyl, 0, 65535),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) IDE_PROC_DEVSET(bios_head, 0, 255),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) IDE_PROC_DEVSET(bios_sect, 0, 63),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) IDE_PROC_DEVSET(failures, 0, 65535),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) IDE_PROC_DEVSET(lun, 0, 7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) IDE_PROC_DEVSET(max_failures, 0, 65535),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) IDE_PROC_DEVSET(multcount, 0, 16),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) IDE_PROC_DEVSET(nowerr, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) IDE_PROC_DEVSET(wcache, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) };