18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci#include <linux/kernel.h>
38c2ecf20Sopenharmony_ci#include <linux/ide.h>
48c2ecf20Sopenharmony_ci#include <linux/slab.h>
58c2ecf20Sopenharmony_ci#include <linux/export.h>
68c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "ide-disk.h"
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_cistatic int smart_enable(ide_drive_t *drive)
118c2ecf20Sopenharmony_ci{
128c2ecf20Sopenharmony_ci	struct ide_cmd cmd;
138c2ecf20Sopenharmony_ci	struct ide_taskfile *tf = &cmd.tf;
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci	memset(&cmd, 0, sizeof(cmd));
168c2ecf20Sopenharmony_ci	tf->feature = ATA_SMART_ENABLE;
178c2ecf20Sopenharmony_ci	tf->lbam    = ATA_SMART_LBAM_PASS;
188c2ecf20Sopenharmony_ci	tf->lbah    = ATA_SMART_LBAH_PASS;
198c2ecf20Sopenharmony_ci	tf->command = ATA_CMD_SMART;
208c2ecf20Sopenharmony_ci	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
218c2ecf20Sopenharmony_ci	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	return ide_no_data_taskfile(drive, &cmd);
248c2ecf20Sopenharmony_ci}
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	struct ide_cmd cmd;
298c2ecf20Sopenharmony_ci	struct ide_taskfile *tf = &cmd.tf;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci	memset(&cmd, 0, sizeof(cmd));
328c2ecf20Sopenharmony_ci	tf->feature = sub_cmd;
338c2ecf20Sopenharmony_ci	tf->nsect   = 0x01;
348c2ecf20Sopenharmony_ci	tf->lbam    = ATA_SMART_LBAM_PASS;
358c2ecf20Sopenharmony_ci	tf->lbah    = ATA_SMART_LBAH_PASS;
368c2ecf20Sopenharmony_ci	tf->command = ATA_CMD_SMART;
378c2ecf20Sopenharmony_ci	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
388c2ecf20Sopenharmony_ci	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
398c2ecf20Sopenharmony_ci	cmd.protocol = ATA_PROT_PIO;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	return ide_raw_taskfile(drive, &cmd, buf, 1);
428c2ecf20Sopenharmony_ci}
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic int idedisk_cache_proc_show(struct seq_file *m, void *v)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	ide_drive_t	*drive = (ide_drive_t *) m->private;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	if (drive->dev_flags & IDE_DFLAG_ID_READ)
498c2ecf20Sopenharmony_ci		seq_printf(m, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2);
508c2ecf20Sopenharmony_ci	else
518c2ecf20Sopenharmony_ci		seq_printf(m, "(none)\n");
528c2ecf20Sopenharmony_ci	return 0;
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic int idedisk_capacity_proc_show(struct seq_file *m, void *v)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	ide_drive_t*drive = (ide_drive_t *)m->private;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	seq_printf(m, "%llu\n", (long long)ide_gd_capacity(drive));
608c2ecf20Sopenharmony_ci	return 0;
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistatic int __idedisk_proc_show(struct seq_file *m, ide_drive_t *drive, u8 sub_cmd)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	u8 *buf;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	buf = kmalloc(SECTOR_SIZE, GFP_KERNEL);
688c2ecf20Sopenharmony_ci	if (!buf)
698c2ecf20Sopenharmony_ci		return -ENOMEM;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	(void)smart_enable(drive);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	if (get_smart_data(drive, buf, sub_cmd) == 0) {
748c2ecf20Sopenharmony_ci		__le16 *val = (__le16 *)buf;
758c2ecf20Sopenharmony_ci		int i;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci		for (i = 0; i < SECTOR_SIZE / 2; i++) {
788c2ecf20Sopenharmony_ci			seq_printf(m, "%04x%c", le16_to_cpu(val[i]),
798c2ecf20Sopenharmony_ci					(i % 8) == 7 ? '\n' : ' ');
808c2ecf20Sopenharmony_ci		}
818c2ecf20Sopenharmony_ci	}
828c2ecf20Sopenharmony_ci	kfree(buf);
838c2ecf20Sopenharmony_ci	return 0;
848c2ecf20Sopenharmony_ci}
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic int idedisk_sv_proc_show(struct seq_file *m, void *v)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	return __idedisk_proc_show(m, m->private, ATA_SMART_READ_VALUES);
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic int idedisk_st_proc_show(struct seq_file *m, void *v)
928c2ecf20Sopenharmony_ci{
938c2ecf20Sopenharmony_ci	return __idedisk_proc_show(m, m->private, ATA_SMART_READ_THRESHOLDS);
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ciide_proc_entry_t ide_disk_proc[] = {
978c2ecf20Sopenharmony_ci	{ "cache",	  S_IFREG|S_IRUGO, idedisk_cache_proc_show	},
988c2ecf20Sopenharmony_ci	{ "capacity",	  S_IFREG|S_IRUGO, idedisk_capacity_proc_show	},
998c2ecf20Sopenharmony_ci	{ "geometry",	  S_IFREG|S_IRUGO, ide_geometry_proc_show	},
1008c2ecf20Sopenharmony_ci	{ "smart_values", S_IFREG|S_IRUSR, idedisk_sv_proc_show		},
1018c2ecf20Sopenharmony_ci	{ "smart_thresholds", S_IFREG|S_IRUSR, idedisk_st_proc_show	},
1028c2ecf20Sopenharmony_ci	{}
1038c2ecf20Sopenharmony_ci};
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciide_devset_rw_field(bios_cyl, bios_cyl);
1068c2ecf20Sopenharmony_ciide_devset_rw_field(bios_head, bios_head);
1078c2ecf20Sopenharmony_ciide_devset_rw_field(bios_sect, bios_sect);
1088c2ecf20Sopenharmony_ciide_devset_rw_field(failures, failures);
1098c2ecf20Sopenharmony_ciide_devset_rw_field(lun, lun);
1108c2ecf20Sopenharmony_ciide_devset_rw_field(max_failures, max_failures);
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ciconst struct ide_proc_devset ide_disk_settings[] = {
1138c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(acoustic,	0,   254),
1148c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(address,	0,     2),
1158c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(bios_cyl,	0, 65535),
1168c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(bios_head,	0,   255),
1178c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(bios_sect,	0,    63),
1188c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(failures,	0, 65535),
1198c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(lun,		0,     7),
1208c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(max_failures,	0, 65535),
1218c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(multcount,	0,    16),
1228c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(nowerr,		0,     1),
1238c2ecf20Sopenharmony_ci	IDE_PROC_DEVSET(wcache,		0,     1),
1248c2ecf20Sopenharmony_ci	{ NULL },
1258c2ecf20Sopenharmony_ci};
126