patch-2.1.79 linux/drivers/block/ide-disk.c
Next file: linux/drivers/block/ide-floppy.c
Previous file: linux/drivers/block/ide-cd.c
Back to the patch index
Back to the overall index
- Lines: 211
- Date:
Sat Jan 10 10:42:55 1998
- Orig file:
v2.1.78/linux/drivers/block/ide-disk.c
- Orig date:
Sun Dec 21 22:36:12 1997
diff -u --recursive --new-file v2.1.78/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/block/ide-disk.c Version 1.03 Nov 30, 1997
+ * linux/drivers/block/ide-disk.c Version 1.04 Jan 7, 1998
*
* Copyright (C) 1994-1998 Linus Torvalds & authors (see below)
*/
@@ -13,11 +13,12 @@
* Version 1.00 move disk only code from ide.c to ide-disk.c
* support optional byte-swapping of all data
* Version 1.01 fix previous byte-swapping code
- * Verions 1.02 remove ", LBA" from drive identification msgs
- * Verions 1.03 fix display of id->buf_size for big-endian
+ * Version 1.02 remove ", LBA" from drive identification msgs
+ * Version 1.03 fix display of id->buf_size for big-endian
+ * Version 1.04 add /proc configurable settings and S.M.A.R.T support
*/
-#define IDEDISK_VERSION "1.03"
+#define IDEDISK_VERSION "1.04"
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -372,17 +373,13 @@
{
MOD_INC_USE_COUNT;
if (drive->removable && drive->usage == 1) {
- byte door_lock[] = {WIN_DOORLOCK,0,0,0};
- struct request rq;
check_disk_change(inode->i_rdev);
- ide_init_drive_cmd (&rq);
- rq.buffer = door_lock;
/*
* Ignore the return code from door_lock,
* since the open() has already succeeded,
* and the door_lock is irrelevant at this point.
*/
- (void) ide_do_drive_cmd(drive, &rq, ide_wait);
+ (void) ide_wait_cmd(drive, WIN_DOORLOCK, 0, 0, 0, NULL);
}
return 0;
}
@@ -390,12 +387,8 @@
static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
{
if (drive->removable && !drive->usage) {
- byte door_unlock[] = {WIN_DOORUNLOCK,0,0,0};
- struct request rq;
invalidate_buffers(inode->i_rdev);
- ide_init_drive_cmd (&rq);
- rq.buffer = door_unlock;
- (void) ide_do_drive_cmd(drive, &rq, ide_wait);
+ (void) ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL);
}
MOD_DEC_USE_COUNT;
}
@@ -481,18 +474,106 @@
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
+static int smart_enable(ide_drive_t *drive)
+{
+ return ide_wait_cmd(drive, WIN_SMART, 0, SMART_ENABLE, 0, NULL);
+}
+
+static int get_smart_values(ide_drive_t *drive, byte *buf)
+{
+ (void) smart_enable(drive);
+ return ide_wait_cmd(drive, WIN_SMART, 0, SMART_READ_VALUES, 1, buf);
+}
+
+static int get_smart_thresholds(ide_drive_t *drive, byte *buf)
+{
+ (void) smart_enable(drive);
+ return ide_wait_cmd(drive, WIN_SMART, 0, SMART_READ_THRESHOLDS, 1, buf);
+}
+
+static int proc_idedisk_read_smart_thresholds
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ ide_drive_t *drive = (ide_drive_t *)data;
+ int len = 0, i = 0;
+
+ if (!get_smart_thresholds(drive, page)) {
+ unsigned short *val = ((unsigned short *)page) + 2;
+ char *out = ((char *)val) + (SECTOR_WORDS * 4);
+ page = out;
+ do {
+ out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+ val += 1;
+ } while (i < (SECTOR_WORDS * 2));
+ len = out - page;
+ }
+ PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
+static int proc_idedisk_read_smart_values
+ (char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+ ide_drive_t *drive = (ide_drive_t *)data;
+ int len = 0, i = 0;
+
+ if (!get_smart_values(drive, page)) {
+ unsigned short *val = ((unsigned short *)page) + 2;
+ char *out = ((char *)val) + (SECTOR_WORDS * 4);
+ page = out;
+ do {
+ out += sprintf(out, "%04x%c", le16_to_cpu(*val), (++i & 7) ? ' ' : '\n');
+ val += 1;
+ } while (i < (SECTOR_WORDS * 2));
+ len = out - page;
+ }
+ PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
static ide_proc_entry_t idedisk_proc[] = {
{ "cache", proc_idedisk_read_cache, NULL },
{ "geometry", proc_ide_read_geometry, NULL },
+ { "smart_values", proc_idedisk_read_smart_values, NULL },
+ { "smart_thresholds", proc_idedisk_read_smart_thresholds, NULL },
{ NULL, NULL, NULL }
};
-int idedisk_init (void);
-static ide_module_t idedisk_module = {
- IDE_DRIVER_MODULE,
- idedisk_init,
- NULL
-};
+static int set_multcount(ide_drive_t *drive, int arg)
+{
+ struct request rq;
+
+ if (drive->special.b.set_multmode)
+ return -EBUSY;
+ ide_init_drive_cmd (&rq);
+ drive->mult_req = arg;
+ drive->special.b.set_multmode = 1;
+ (void) ide_do_drive_cmd (drive, &rq, ide_wait);
+ return (drive->mult_count == arg) ? 0 : -EIO;
+}
+
+static int set_nowerr(ide_drive_t *drive, int arg)
+{
+ drive->nowerr = arg;
+ drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
+ return 0;
+}
+
+static void idedisk_add_settings(ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+ int major = HWIF(drive)->major;
+ int minor = drive->select.b.unit << PARTN_BITS;
+
+ ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_SHORT, 0, 1023, 1, 1, &drive->bios_cyl, NULL);
+ ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
+ ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
+ ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL);
+ ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 2, &drive->mult_count, set_multcount);
+ ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr);
+ ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
+ ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL);
+ ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
+
+}
/*
* IDE subdriver functions, registered with ide.c
@@ -517,6 +598,14 @@
idedisk_proc /* proc */
};
+int idedisk_init (void);
+static ide_module_t idedisk_module = {
+ IDE_DRIVER_MODULE,
+ idedisk_init,
+ &idedisk_driver,
+ NULL
+};
+
static int idedisk_cleanup (ide_drive_t *drive)
{
return ide_unregister_subdriver(drive);
@@ -527,6 +616,8 @@
struct hd_driveid *id = drive->id;
unsigned long capacity, check;
+ idedisk_add_settings(drive);
+
if (id == NULL)
return;
@@ -615,7 +706,7 @@
int failed = 0;
MOD_INC_USE_COUNT;
- while ((drive = ide_scan_devices (ide_disk, NULL, failed++)) != NULL) {
+ while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, NULL, failed++)) != NULL) {
/* SunDisk drives: ignore "second" drive; can mess up non-Sun systems! FIXME */
struct hd_driveid *id = drive->id;
@@ -650,7 +741,7 @@
ide_drive_t *drive;
int failed = 0;
- while ((drive = ide_scan_devices (ide_disk, &idedisk_driver, failed)) != NULL)
+ while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL)
if (idedisk_cleanup (drive)) {
printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
failed++;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov