| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 1 | #include <linux/kernel.h> | 
|  | 2 | #include <linux/ide.h> | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 3 |  | 
|  | 4 | #include "ide-disk.h" | 
|  | 5 |  | 
|  | 6 | static int smart_enable(ide_drive_t *drive) | 
|  | 7 | { | 
| Bartlomiej Zolnierkiewicz | 22aa4b3 | 2009-03-27 12:46:37 +0100 | [diff] [blame] | 8 | struct ide_cmd cmd; | 
|  | 9 | struct ide_taskfile *tf = &cmd.tf; | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 10 |  | 
| Bartlomiej Zolnierkiewicz | 22aa4b3 | 2009-03-27 12:46:37 +0100 | [diff] [blame] | 11 | memset(&cmd, 0, sizeof(cmd)); | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 12 | tf->feature = ATA_SMART_ENABLE; | 
|  | 13 | tf->lbam    = ATA_SMART_LBAM_PASS; | 
|  | 14 | tf->lbah    = ATA_SMART_LBAH_PASS; | 
|  | 15 | tf->command = ATA_CMD_SMART; | 
| Sergei Shtylyov | 60f8501 | 2009-04-08 14:13:01 +0200 | [diff] [blame] | 16 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; | 
|  | 17 | cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE; | 
| Bartlomiej Zolnierkiewicz | 22aa4b3 | 2009-03-27 12:46:37 +0100 | [diff] [blame] | 18 |  | 
|  | 19 | return ide_no_data_taskfile(drive, &cmd); | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 20 | } | 
|  | 21 |  | 
|  | 22 | static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd) | 
|  | 23 | { | 
| Bartlomiej Zolnierkiewicz | 22aa4b3 | 2009-03-27 12:46:37 +0100 | [diff] [blame] | 24 | struct ide_cmd cmd; | 
|  | 25 | struct ide_taskfile *tf = &cmd.tf; | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 26 |  | 
| Bartlomiej Zolnierkiewicz | 22aa4b3 | 2009-03-27 12:46:37 +0100 | [diff] [blame] | 27 | memset(&cmd, 0, sizeof(cmd)); | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 28 | tf->feature = sub_cmd; | 
|  | 29 | tf->nsect   = 0x01; | 
|  | 30 | tf->lbam    = ATA_SMART_LBAM_PASS; | 
|  | 31 | tf->lbah    = ATA_SMART_LBAH_PASS; | 
|  | 32 | tf->command = ATA_CMD_SMART; | 
| Sergei Shtylyov | 60f8501 | 2009-04-08 14:13:01 +0200 | [diff] [blame] | 33 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; | 
|  | 34 | cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE; | 
| Bartlomiej Zolnierkiewicz | 0dfb991 | 2009-03-27 12:46:39 +0100 | [diff] [blame] | 35 | cmd.protocol = ATA_PROT_PIO; | 
| Bartlomiej Zolnierkiewicz | 3937585 | 2009-03-27 12:46:32 +0100 | [diff] [blame] | 36 |  | 
| Bartlomiej Zolnierkiewicz | 22aa4b3 | 2009-03-27 12:46:37 +0100 | [diff] [blame] | 37 | return ide_raw_taskfile(drive, &cmd, buf, 1); | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 38 | } | 
|  | 39 |  | 
|  | 40 | static int proc_idedisk_read_cache | 
|  | 41 | (char *page, char **start, off_t off, int count, int *eof, void *data) | 
|  | 42 | { | 
|  | 43 | ide_drive_t	*drive = (ide_drive_t *) data; | 
|  | 44 | char		*out = page; | 
|  | 45 | int		len; | 
|  | 46 |  | 
|  | 47 | if (drive->dev_flags & IDE_DFLAG_ID_READ) | 
|  | 48 | len = sprintf(out, "%i\n", drive->id[ATA_ID_BUF_SIZE] / 2); | 
|  | 49 | else | 
|  | 50 | len = sprintf(out, "(none)\n"); | 
|  | 51 |  | 
|  | 52 | PROC_IDE_READ_RETURN(page, start, off, count, eof, len); | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 | static int proc_idedisk_read_capacity | 
|  | 56 | (char *page, char **start, off_t off, int count, int *eof, void *data) | 
|  | 57 | { | 
|  | 58 | ide_drive_t*drive = (ide_drive_t *)data; | 
|  | 59 | int len; | 
|  | 60 |  | 
| Bartlomiej Zolnierkiewicz | 5fef0e5 | 2008-10-17 18:09:12 +0200 | [diff] [blame] | 61 | len = sprintf(page, "%llu\n", (long long)ide_gd_capacity(drive)); | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 62 |  | 
|  | 63 | PROC_IDE_READ_RETURN(page, start, off, count, eof, len); | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | static int proc_idedisk_read_smart(char *page, char **start, off_t off, | 
|  | 67 | int count, int *eof, void *data, u8 sub_cmd) | 
|  | 68 | { | 
|  | 69 | ide_drive_t	*drive = (ide_drive_t *)data; | 
|  | 70 | int		len = 0, i = 0; | 
|  | 71 |  | 
| Bartlomiej Zolnierkiewicz | 3937585 | 2009-03-27 12:46:32 +0100 | [diff] [blame] | 72 | (void)smart_enable(drive); | 
|  | 73 |  | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 74 | if (get_smart_data(drive, page, sub_cmd) == 0) { | 
|  | 75 | unsigned short *val = (unsigned short *) page; | 
|  | 76 | char *out = (char *)val + SECTOR_SIZE; | 
|  | 77 |  | 
|  | 78 | page = out; | 
|  | 79 | do { | 
|  | 80 | out += sprintf(out, "%04x%c", le16_to_cpu(*val), | 
|  | 81 | (++i & 7) ? ' ' : '\n'); | 
|  | 82 | val += 1; | 
|  | 83 | } while (i < SECTOR_SIZE / 2); | 
|  | 84 | len = out - page; | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | PROC_IDE_READ_RETURN(page, start, off, count, eof, len); | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | static int proc_idedisk_read_sv | 
|  | 91 | (char *page, char **start, off_t off, int count, int *eof, void *data) | 
|  | 92 | { | 
|  | 93 | return proc_idedisk_read_smart(page, start, off, count, eof, data, | 
|  | 94 | ATA_SMART_READ_VALUES); | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | static int proc_idedisk_read_st | 
|  | 98 | (char *page, char **start, off_t off, int count, int *eof, void *data) | 
|  | 99 | { | 
|  | 100 | return proc_idedisk_read_smart(page, start, off, count, eof, data, | 
|  | 101 | ATA_SMART_READ_THRESHOLDS); | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | ide_proc_entry_t ide_disk_proc[] = { | 
|  | 105 | { "cache",	  S_IFREG|S_IRUGO, proc_idedisk_read_cache,    NULL }, | 
|  | 106 | { "capacity",	  S_IFREG|S_IRUGO, proc_idedisk_read_capacity, NULL }, | 
|  | 107 | { "geometry",	  S_IFREG|S_IRUGO, proc_ide_read_geometry,     NULL }, | 
|  | 108 | { "smart_values", S_IFREG|S_IRUSR, proc_idedisk_read_sv,       NULL }, | 
|  | 109 | { "smart_thresholds", S_IFREG|S_IRUSR, proc_idedisk_read_st,   NULL }, | 
|  | 110 | { NULL, 0, NULL, NULL } | 
|  | 111 | }; | 
|  | 112 |  | 
|  | 113 | ide_devset_rw_field(bios_cyl, bios_cyl); | 
|  | 114 | ide_devset_rw_field(bios_head, bios_head); | 
|  | 115 | ide_devset_rw_field(bios_sect, bios_sect); | 
|  | 116 | ide_devset_rw_field(failures, failures); | 
|  | 117 | ide_devset_rw_field(lun, lun); | 
|  | 118 | ide_devset_rw_field(max_failures, max_failures); | 
|  | 119 |  | 
|  | 120 | const struct ide_proc_devset ide_disk_settings[] = { | 
|  | 121 | IDE_PROC_DEVSET(acoustic,	0,   254), | 
|  | 122 | IDE_PROC_DEVSET(address,	0,     2), | 
|  | 123 | IDE_PROC_DEVSET(bios_cyl,	0, 65535), | 
|  | 124 | IDE_PROC_DEVSET(bios_head,	0,   255), | 
|  | 125 | IDE_PROC_DEVSET(bios_sect,	0,    63), | 
|  | 126 | IDE_PROC_DEVSET(failures,	0, 65535), | 
|  | 127 | IDE_PROC_DEVSET(lun,		0,     7), | 
|  | 128 | IDE_PROC_DEVSET(max_failures,	0, 65535), | 
|  | 129 | IDE_PROC_DEVSET(multcount,	0,    16), | 
|  | 130 | IDE_PROC_DEVSET(nowerr,		0,     1), | 
|  | 131 | IDE_PROC_DEVSET(wcache,		0,     1), | 
| Hannes Eder | 71bfc7a | 2009-03-05 16:10:56 +0100 | [diff] [blame] | 132 | { NULL }, | 
| Bartlomiej Zolnierkiewicz | 06b8951 | 2008-10-13 21:39:45 +0200 | [diff] [blame] | 133 | }; |