mutex_unlock(&idedisk_ref_mutex);
}
-/*
- * lba_capacity_is_ok() performs a sanity check on the claimed "lba_capacity"
- * value for this drive (from its reported identification information).
- *
- * Returns: 1 if lba_capacity looks sensible
- * 0 otherwise
- *
- * It is called only once for each drive.
- */
-static int lba_capacity_is_ok(u16 *id)
-{
- unsigned long lba_sects, chs_sects, head, tail;
-
- /* No non-LBA info .. so valid! */
- if (id[ATA_ID_CYLS] == 0)
- return 1;
-
- lba_sects = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
-
- /*
- * The ATA spec tells large drives to return
- * C/H/S = 16383/16/63 independent of their size.
- * Some drives can be jumpered to use 15 heads instead of 16.
- * Some drives can be jumpered to use 4092 cyls instead of 16383.
- */
- if ((id[ATA_ID_CYLS] == 16383 ||
- (id[ATA_ID_CYLS] == 4092 && id[ATA_ID_CUR_CYLS] == 16383)) &&
- id[ATA_ID_SECTORS] == 63 &&
- (id[ATA_ID_HEADS] == 15 || id[ATA_ID_HEADS] == 16) &&
- (lba_sects >= 16383 * 63 * id[ATA_ID_HEADS]))
- return 1;
-
- chs_sects = id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * id[ATA_ID_SECTORS];
-
- /* perform a rough sanity check on lba_sects: within 10% is OK */
- if ((lba_sects - chs_sects) < chs_sects/10)
- return 1;
-
- /* some drives have the word order reversed */
- head = ((lba_sects >> 16) & 0xffff);
- tail = (lba_sects & 0xffff);
- lba_sects = (head | (tail << 16));
- if ((lba_sects - chs_sects) < chs_sects/10) {
- *(__le32 *)&id[ATA_ID_LBA_CAPACITY] = __cpu_to_le32(lba_sects);
- return 1; /* lba_capacity is (now) good */
- }
-
- return 0; /* lba_capacity value may be bad */
-}
-
static const u8 ide_rw_cmds[] = {
ATA_CMD_READ_MULTI,
ATA_CMD_WRITE_MULTI,
drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
if (hpa)
idedisk_check_hpa(drive);
- } else if (ata_id_has_lba(id) && lba_capacity_is_ok(id)) {
+ } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) {
/* drive speaks 28-bit LBA */
drive->select.b.lba = 1;
drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
BUG_ON(task == NULL);
memset(task, 0, sizeof(*task));
- if (ide_id_has_flush_cache_ext(drive->id) &&
+ if (ata_id_flush_ext_enabled(drive->id) &&
(drive->capacity64 >= (1UL << 28)))
task->tf.command = ATA_CMD_FLUSH_EXT;
else
if (arg < 0 || arg > 1)
return -EINVAL;
- if (ide_spin_wait_hwgroup(drive))
- return -EBUSY;
drive->nowerr = arg;
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
- spin_unlock_irq(&ide_lock);
return 0;
}
+static int ide_do_setfeature(ide_drive_t *drive, u8 feature, u8 nsect)
+{
+ ide_task_t task;
+
+ memset(&task, 0, sizeof(task));
+ task.tf.feature = feature;
+ task.tf.nsect = nsect;
+ task.tf.command = ATA_CMD_SET_FEATURES;
+ task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+
+ return ide_no_data_taskfile(drive, &task);
+}
+
static void update_ordered(ide_drive_t *drive)
{
u16 *id = drive->id;
capacity = idedisk_capacity(drive);
barrier = ata_id_flush_enabled(id) && !drive->noflush &&
(drive->addressing == 0 || capacity <= (1ULL << 28) ||
- ide_id_has_flush_cache_ext(id));
+ ata_id_flush_ext_enabled(id));
printk(KERN_INFO "%s: cache flushes %ssupported\n",
drive->name, barrier ? "" : "not ");
static int set_wcache(ide_drive_t *drive, int arg)
{
- ide_task_t args;
int err = 1;
if (arg < 0 || arg > 1)
return -EINVAL;
if (ata_id_flush_enabled(drive->id)) {
- memset(&args, 0, sizeof(ide_task_t));
- args.tf.feature = arg ?
- SETFEATURES_WC_ON : SETFEATURES_WC_OFF;
- args.tf.command = ATA_CMD_SET_FEATURES;
- args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- err = ide_no_data_taskfile(drive, &args);
+ err = ide_do_setfeature(drive,
+ arg ? SETFEATURES_WC_ON : SETFEATURES_WC_OFF, 0);
if (err == 0)
drive->wcache = arg;
}
ide_task_t args;
memset(&args, 0, sizeof(ide_task_t));
- if (ide_id_has_flush_cache_ext(drive->id))
+ if (ata_id_flush_ext_enabled(drive->id))
args.tf.command = ATA_CMD_FLUSH_EXT;
else
args.tf.command = ATA_CMD_FLUSH;
static int set_acoustic(ide_drive_t *drive, int arg)
{
- ide_task_t args;
-
if (arg < 0 || arg > 254)
return -EINVAL;
- memset(&args, 0, sizeof(ide_task_t));
- args.tf.feature = arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF;
- args.tf.nsect = arg;
- args.tf.command = ATA_CMD_SET_FEATURES;
- args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- ide_no_data_taskfile(drive, &args);
+ ide_do_setfeature(drive,
+ arg ? SETFEATURES_AAM_ON : SETFEATURES_AAM_OFF, arg);
+
drive->acoustic = arg;
+
return 0;
}
-ide_devset_get(lba_addressing, addressing);
+ide_devset_get(addressing, addressing);
/*
* drive->addressing:
* 1: 48-bit
* 2: 48-bit capable doing 28-bit
*/
-static int set_lba_addressing(ide_drive_t *drive, int arg)
+static int set_addressing(ide_drive_t *drive, int arg)
{
if (arg < 0 || arg > 2)
return -EINVAL;
- drive->addressing = 0;
-
- if (drive->hwif->host_flags & IDE_HFLAG_NO_LBA48)
- return 0;
-
- if (ata_id_lba48_enabled(drive->id) == 0)
+ if (arg && ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+ ata_id_lba48_enabled(drive->id) == 0))
return -EIO;
+ if (arg == 2)
+ arg = 0;
+
drive->addressing = arg;
return 0;
}
+ide_devset_rw(acoustic, acoustic);
+ide_devset_rw(address, addressing);
+ide_devset_rw(multcount, multcount);
+ide_devset_rw(wcache, wcache);
+
+ide_devset_rw_sync(nowerr, nowerr);
+
#ifdef CONFIG_IDE_PROC_FS
-ide_devset_rw_nolock(acoustic, 0, 254, acoustic);
-ide_devset_rw_nolock(address, 0, 2, lba_addressing);
-ide_devset_rw_nolock(multcount, 0, 16, multcount);
-ide_devset_rw_nolock(nowerr, 0, 1, nowerr);
-ide_devset_rw_nolock(wcache, 0, 1, wcache);
-
-ide_devset_rw(bios_cyl, 0, 65535, bios_cyl);
-ide_devset_rw(bios_head, 0, 255, bios_head);
-ide_devset_rw(bios_sect, 0, 63, bios_sect);
-ide_devset_rw(failures, 0, 65535, failures);
-ide_devset_rw(lun, 0, 7, lun);
-ide_devset_rw(max_failures, 0, 65535, max_failures);
-
-static const struct ide_devset *idedisk_settings[] = {
- &ide_devset_acoustic,
- &ide_devset_address,
- &ide_devset_bios_cyl,
- &ide_devset_bios_head,
- &ide_devset_bios_sect,
- &ide_devset_failures,
- &ide_devset_lun,
- &ide_devset_max_failures,
- &ide_devset_multcount,
- &ide_devset_nowerr,
- &ide_devset_wcache,
- NULL
+ide_devset_rw_field(bios_cyl, bios_cyl);
+ide_devset_rw_field(bios_head, bios_head);
+ide_devset_rw_field(bios_sect, bios_sect);
+ide_devset_rw_field(failures, failures);
+ide_devset_rw_field(lun, lun);
+ide_devset_rw_field(max_failures, max_failures);
+
+static const struct ide_proc_devset idedisk_settings[] = {
+ IDE_PROC_DEVSET(acoustic, 0, 254),
+ IDE_PROC_DEVSET(address, 0, 2),
+ IDE_PROC_DEVSET(bios_cyl, 0, 65535),
+ IDE_PROC_DEVSET(bios_head, 0, 255),
+ IDE_PROC_DEVSET(bios_sect, 0, 63),
+ IDE_PROC_DEVSET(failures, 0, 65535),
+ IDE_PROC_DEVSET(lun, 0, 7),
+ IDE_PROC_DEVSET(max_failures, 0, 65535),
+ IDE_PROC_DEVSET(multcount, 0, 16),
+ IDE_PROC_DEVSET(nowerr, 0, 1),
+ IDE_PROC_DEVSET(wcache, 0, 1),
+ { 0 },
};
#endif
drive->doorlocking = 1;
}
- (void)set_lba_addressing(drive, 1);
+ (void)set_addressing(drive, 1);
if (drive->addressing == 1) {
int max_s = 2048;
return 0;
}
+static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
+{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address },
+{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount },
+{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr },
+{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache },
+{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic },
+{ 0 }
+};
+
static int idedisk_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- unsigned long flags;
struct block_device *bdev = inode->i_bdev;
struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
ide_drive_t *drive = idkp->drive;
- int err, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
-
- switch (cmd) {
- case HDIO_GET_ADDRESS: getfunc = get_lba_addressing; goto read_val;
- case HDIO_GET_MULTCOUNT: getfunc = get_multcount; goto read_val;
- case HDIO_GET_NOWERR: getfunc = get_nowerr; goto read_val;
- case HDIO_GET_WCACHE: getfunc = get_wcache; goto read_val;
- case HDIO_GET_ACOUSTIC: getfunc = get_acoustic; goto read_val;
- case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
- case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
- case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
- case HDIO_SET_WCACHE: setfunc = set_wcache; goto set_val;
- case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
- }
+ int err;
- return generic_ide_ioctl(drive, file, bdev, cmd, arg);
+ err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
+ if (err != -EOPNOTSUPP)
+ return err;
-read_val:
- mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
- err = getfunc(drive);
- spin_unlock_irqrestore(&ide_lock, flags);
- mutex_unlock(&ide_setting_mtx);
- return err >= 0 ? put_user(err, (long __user *)arg) : err;
-
-set_val:
- if (bdev != bdev->bd_contains)
- err = -EINVAL;
- else {
- if (!capable(CAP_SYS_ADMIN))
- err = -EACCES;
- else {
- mutex_lock(&ide_setting_mtx);
- err = setfunc(drive, arg);
- mutex_unlock(&ide_setting_mtx);
- }
- }
- return err;
+ return generic_ide_ioctl(drive, file, bdev, cmd, arg);
}
static int idedisk_media_changed(struct gendisk *disk)