ide: fix HDIO_DRIVE_TASK[FILE] ioctls for CHS commands on LBA devices
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Mon, 13 Oct 2008 19:39:38 +0000 (21:39 +0200)
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Mon, 13 Oct 2008 19:39:38 +0000 (21:39 +0200)
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>
drivers/ide/ide-disk.c
drivers/ide/ide-io.c
include/linux/ide.h

index c35de54dfc228b0de5aadb338daed99e9cf34b83..6eb9fea32a56b63666508ea78fbfd5364a318336 100644 (file)
@@ -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;
index 11b602bb5741e0d960ab85dac9c24ba4de1ebc0f..623f6c246cf50deef82dd6a595ebb658f96b2c38 100644 (file)
@@ -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;
 }
 
index fdec0108dba17436c3ed21d4966218a97b2d29f9..cf7ec3a9d173183dc264197b4f031f8cad2a47a8 100644 (file)
@@ -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 {