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