diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-13 23:39:38 +0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-13 23:39:38 +0400 |
commit | d1d76714e2f0c520b6c2a84ab5b050d0b3244949 (patch) | |
tree | 605b10d60a0bcc59441ebe87503c03016df08dd1 | |
parent | c67c216d810a05fffdbdbdf1b81048f0d4759287 (diff) | |
download | linux-d1d76714e2f0c520b6c2a84ab5b050d0b3244949.tar.xz |
ide: fix HDIO_DRIVE_TASK[FILE] ioctls for CHS commands on LBA devices
Add IDE_DFLAG_LBA device flag and use it instead of ->select.b.lba.
Since ->tf_load uses ->select.all for ATA Device/Head register this
fixes HDIO_DRIVE_TASK[FILE] ioctls for CHS commands on LBA devices.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/ide-disk.c | 33 | ||||
-rw-r--r-- | drivers/ide/ide-io.c | 4 | ||||
-rw-r--r-- | include/linux/ide.h | 1 |
3 files changed, 23 insertions, 15 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index c35de54dfc22..6eb9fea32a56 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -162,7 +162,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, memset(&task, 0, sizeof(task)); task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - if (drive->select.b.lba) { + if (drive->dev_flags & IDE_DFLAG_LBA) { if (lba48) { pr_debug("%s: LBA=0x%012llx\n", drive->name, (unsigned long long)block); @@ -187,6 +187,8 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, tf->lbah = block >>= 8; tf->device = (block >> 8) & 0xf; } + + tf->device |= ATA_LBA; } else { unsigned int sect, head, cyl, track; @@ -384,28 +386,32 @@ static void idedisk_check_hpa(ide_drive_t *drive) static void init_idedisk_capacity(ide_drive_t *drive) { u16 *id = drive->id; - /* - * If this drive supports the Host Protected Area feature set, - * then we may need to change our opinion about the drive's capacity. - */ - int hpa = ata_id_hpa_enabled(id); + int lba; if (ata_id_lba48_enabled(id)) { /* drive speaks 48-bit LBA */ - drive->select.b.lba = 1; + lba = 1; drive->capacity64 = ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); - if (hpa) - idedisk_check_hpa(drive); } else if (ata_id_has_lba(id) && ata_id_is_lba_capacity_ok(id)) { /* drive speaks 28-bit LBA */ - drive->select.b.lba = 1; + lba = 1; drive->capacity64 = ata_id_u32(id, ATA_ID_LBA_CAPACITY); - if (hpa) - idedisk_check_hpa(drive); } else { /* drive speaks boring old 28-bit CHS */ + lba = 0; drive->capacity64 = drive->cyl * drive->head * drive->sect; } + + if (lba) { + drive->dev_flags |= IDE_DFLAG_LBA; + + /* + * If this device supports the Host Protected Area feature set, + * then we may need to change our opinion about its capacity. + */ + if (ata_id_hpa_enabled(id)) + idedisk_check_hpa(drive); + } } static sector_t idedisk_capacity(ide_drive_t *drive) @@ -1110,7 +1116,8 @@ static int ide_disk_probe(ide_drive_t *drive) drive->driver_data = idkp; idedisk_setup(drive); - if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { + if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 && + (drive->head == 0 || drive->head > 16)) { printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); drive->dev_flags &= ~IDE_DFLAG_ATTACH; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 11b602bb5741..623f6c246cf5 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -383,7 +383,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 } else if (stat & ATA_ERR) { /* err has different meaning on cdrom and tape */ if (err == ATA_ABORTED) { - if (drive->select.b.lba && + if ((drive->dev_flags & IDE_DFLAG_LBA) && /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) return ide_stopped; @@ -513,7 +513,7 @@ static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) tf->lbal = drive->sect; tf->lbam = drive->cyl; tf->lbah = drive->cyl >> 8; - tf->device = ((drive->head - 1) | drive->select.all) & ~ATA_LBA; + tf->device = (drive->head - 1) | drive->select.all; tf->command = ATA_CMD_INIT_DEV_PARAMS; } diff --git a/include/linux/ide.h b/include/linux/ide.h index fdec0108dba1..cf7ec3a9d173 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -502,6 +502,7 @@ enum { IDE_DFLAG_NOWERR = (1 << 24), /* retrying in PIO */ IDE_DFLAG_DMA_PIO_RETRY = (1 << 25), + IDE_DFLAG_LBA = (1 << 26), }; struct ide_drive_s { |