Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
[linux-2.6] / drivers / ide / ide-disk_proc.c
1 #include <linux/kernel.h>
2 #include <linux/ide.h>
3
4 #include "ide-disk.h"
5
6 static int smart_enable(ide_drive_t *drive)
7 {
8         struct ide_cmd cmd;
9         struct ide_taskfile *tf = &cmd.tf;
10
11         memset(&cmd, 0, sizeof(cmd));
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;
16         cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
17         cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
18
19         return ide_no_data_taskfile(drive, &cmd);
20 }
21
22 static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
23 {
24         struct ide_cmd cmd;
25         struct ide_taskfile *tf = &cmd.tf;
26
27         memset(&cmd, 0, sizeof(cmd));
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;
33         cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
34         cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
35         cmd.protocol = ATA_PROT_PIO;
36
37         return ide_raw_taskfile(drive, &cmd, buf, 1);
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
61         len = sprintf(page, "%llu\n", (long long)ide_gd_capacity(drive));
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
72         (void)smart_enable(drive);
73
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),
132         { NULL },
133 };