sector_t block)
{
ide_hwif_t *hwif = drive->hwif;
- u16 nsectors = (u16)rq->nr_sectors;
+ u16 nsectors = (u16)blk_rq_sectors(rq);
u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48);
u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
struct ide_cmd cmd;
ide_startstop_t rc;
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
- if (block + rq->nr_sectors > 1ULL << 28)
+ if (block + blk_rq_sectors(rq) > 1ULL << 28)
dma = 0;
else
lba48 = 0;
}
memset(&cmd, 0, sizeof(cmd));
- cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
if (drive->dev_flags & IDE_DFLAG_LBA) {
if (lba48) {
pr_debug("%s: LBA=0x%012llx\n", drive->name,
(unsigned long long)block);
- tf->hob_nsect = (nsectors >> 8) & 0xff;
- tf->hob_lbal = (u8)(block >> 24);
- if (sizeof(block) != 4) {
- tf->hob_lbam = (u8)((u64)block >> 32);
- tf->hob_lbah = (u8)((u64)block >> 40);
- }
-
tf->nsect = nsectors & 0xff;
tf->lbal = (u8) block;
tf->lbam = (u8)(block >> 8);
tf->lbah = (u8)(block >> 16);
+ tf->device = ATA_LBA;
+
+ tf = &cmd.hob;
+ tf->nsect = (nsectors >> 8) & 0xff;
+ tf->lbal = (u8)(block >> 24);
+ if (sizeof(block) != 4) {
+ tf->lbam = (u8)((u64)block >> 32);
+ tf->lbah = (u8)((u64)block >> 40);
+ }
- cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+ cmd.valid.out.hob = IDE_VALID_OUT_HOB;
+ cmd.valid.in.hob = IDE_VALID_IN_HOB;
+ cmd.tf_flags |= IDE_TFLAG_LBA48;
} else {
tf->nsect = nsectors & 0xff;
tf->lbal = block;
tf->lbam = block >>= 8;
tf->lbah = block >>= 8;
- tf->device = (block >> 8) & 0xf;
+ tf->device = ((block >> 8) & 0xf) | ATA_LBA;
}
-
- tf->device |= ATA_LBA;
} else {
unsigned int sect, head, cyl, track;
ide_hwif_t *hwif = drive->hwif;
BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED);
-
- if (!blk_fs_request(rq)) {
- blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command");
- if (rq->errors == 0)
- rq->errors = -EIO;
- ide_complete_rq(drive, -EIO, ide_rq_bytes(rq));
- return ide_stopped;
- }
+ BUG_ON(!blk_fs_request(rq));
ledtrig_ide_activity();
- pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n",
+ pr_debug("%s: %sing: block=%llu, sectors=%u, buffer=0x%08lx\n",
drive->name, rq_data_dir(rq) == READ ? "read" : "writ",
- (unsigned long long)block, rq->nr_sectors,
+ (unsigned long long)block, blk_rq_sectors(rq),
(unsigned long)rq->buffer);
if (hwif->rw_disk)
tf->command = ATA_CMD_READ_NATIVE_MAX;
tf->device = ATA_LBA;
- cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- if (lba48)
- cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+ cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
+ if (lba48) {
+ cmd.valid.out.hob = IDE_VALID_OUT_HOB;
+ cmd.valid.in.hob = IDE_VALID_IN_HOB;
+ cmd.tf_flags = IDE_TFLAG_LBA48;
+ }
ide_no_data_taskfile(drive, &cmd);
/* if OK, compute maximum address value */
- if ((tf->status & 0x01) == 0)
- addr = ide_get_lba_addr(tf, lba48) + 1;
+ if (!(tf->status & ATA_ERR))
+ addr = ide_get_lba_addr(&cmd, lba48) + 1;
return addr;
}
tf->lbam = (addr_req >>= 8) & 0xff;
tf->lbah = (addr_req >>= 8) & 0xff;
if (lba48) {
- tf->hob_lbal = (addr_req >>= 8) & 0xff;
- tf->hob_lbam = (addr_req >>= 8) & 0xff;
- tf->hob_lbah = (addr_req >>= 8) & 0xff;
+ cmd.hob.lbal = (addr_req >>= 8) & 0xff;
+ cmd.hob.lbam = (addr_req >>= 8) & 0xff;
+ cmd.hob.lbah = (addr_req >>= 8) & 0xff;
tf->command = ATA_CMD_SET_MAX_EXT;
} else {
tf->device = (addr_req >>= 8) & 0x0f;
}
tf->device |= ATA_LBA;
- cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
- if (lba48)
- cmd.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+ cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
+ if (lba48) {
+ cmd.valid.out.hob = IDE_VALID_OUT_HOB;
+ cmd.valid.in.hob = IDE_VALID_IN_HOB;
+ cmd.tf_flags = IDE_TFLAG_LBA48;
+ }
ide_no_data_taskfile(drive, &cmd);
/* if OK, compute maximum address value */
- if ((tf->status & 0x01) == 0)
- addr_set = ide_get_lba_addr(tf, lba48) + 1;
+ if (!(tf->status & ATA_ERR))
+ addr_set = ide_get_lba_addr(&cmd, lba48) + 1;
return addr_set;
}
{ NULL, NULL }
};
-static void idedisk_check_hpa(ide_drive_t *drive)
+static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48)
{
- unsigned long long capacity, set_max;
- int lba48 = ata_id_lba48_enabled(drive->id);
+ u64 capacity, set_max;
capacity = drive->capacity64;
-
- set_max = idedisk_read_native_max_address(drive, lba48);
+ set_max = idedisk_read_native_max_address(drive, lba48);
if (ide_in_drive_list(drive->id, hpa_list)) {
/*
set_max--;
}
+ return set_max;
+}
+
+static u64 ide_disk_hpa_set_capacity(ide_drive_t *drive, u64 set_max, int lba48)
+{
+ set_max = idedisk_set_max_address(drive, set_max, lba48);
+ if (set_max)
+ drive->capacity64 = set_max;
+
+ return set_max;
+}
+
+static void idedisk_check_hpa(ide_drive_t *drive)
+{
+ u64 capacity, set_max;
+ int lba48 = ata_id_lba48_enabled(drive->id);
+
+ capacity = drive->capacity64;
+ set_max = ide_disk_hpa_get_native_capacity(drive, lba48);
+
if (set_max <= capacity)
return;
+ drive->probed_capacity = set_max;
+
printk(KERN_INFO "%s: Host Protected Area detected.\n"
"\tcurrent capacity is %llu sectors (%llu MB)\n"
"\tnative capacity is %llu sectors (%llu MB)\n",
capacity, sectors_to_MB(capacity),
set_max, sectors_to_MB(set_max));
- set_max = idedisk_set_max_address(drive, set_max, lba48);
+ if ((drive->dev_flags & IDE_DFLAG_NOHPA) == 0)
+ return;
- if (set_max) {
- drive->capacity64 = set_max;
+ set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48);
+ if (set_max)
printk(KERN_INFO "%s: Host Protected Area disabled.\n",
drive->name);
- }
}
static int ide_disk_get_capacity(ide_drive_t *drive)
drive->capacity64 = drive->cyl * drive->head * drive->sect;
}
+ drive->probed_capacity = drive->capacity64;
+
if (lba) {
drive->dev_flags |= IDE_DFLAG_LBA;
"%llu sectors (%llu MB)\n",
drive->name, (unsigned long long)drive->capacity64,
sectors_to_MB(drive->capacity64));
- drive->capacity64 = 1ULL << 28;
+ drive->probed_capacity = drive->capacity64 = 1ULL << 28;
}
if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) &&
return 0;
}
+static u64 ide_disk_set_capacity(ide_drive_t *drive, u64 capacity)
+{
+ u64 set = min(capacity, drive->probed_capacity);
+ u16 *id = drive->id;
+ int lba48 = ata_id_lba48_enabled(id);
+
+ if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 ||
+ ata_id_hpa_enabled(id) == 0)
+ goto out;
+
+ /*
+ * according to the spec the SET MAX ADDRESS command shall be
+ * immediately preceded by a READ NATIVE MAX ADDRESS command
+ */
+ capacity = ide_disk_hpa_get_native_capacity(drive, lba48);
+ if (capacity == 0)
+ goto out;
+
+ set = ide_disk_hpa_set_capacity(drive, set, lba48);
+ if (set) {
+ /* needed for ->resume to disable HPA */
+ drive->dev_flags |= IDE_DFLAG_NOHPA;
+ return set;
+ }
+out:
+ return drive->capacity64;
+}
+
static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
{
ide_drive_t *drive = q->queuedata;
cmd->tf.command = ATA_CMD_FLUSH_EXT;
else
cmd->tf.command = ATA_CMD_FLUSH;
- cmd->tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE |
- IDE_TFLAG_DYN;
+ cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd->tf_flags = IDE_TFLAG_DYN;
cmd->protocol = ATA_PROT_NODATA;
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
- rq->cmd_flags |= REQ_SOFTBARRIER;
rq->special = cmd;
+ cmd->rq = rq;
}
ide_devset_get(multcount, mult_count);
if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff))
return -EINVAL;
- if (drive->special.b.set_multmode)
+ if (drive->special_flags & IDE_SFLAG_SET_MULTMODE)
return -EBUSY;
rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
drive->mult_req = arg;
- drive->special.b.set_multmode = 1;
+ drive->special_flags |= IDE_SFLAG_SET_MULTMODE;
error = blk_execute_rq(drive->queue, NULL, rq, 0);
blk_put_request(rq);
cmd.tf.feature = feature;
cmd.tf.nsect = nsect;
cmd.tf.command = ATA_CMD_SET_FEATURES;
- cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
return ide_no_data_taskfile(drive, &cmd);
}
cmd.tf.command = ATA_CMD_FLUSH_EXT;
else
cmd.tf.command = ATA_CMD_FLUSH;
- cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
return ide_no_data_taskfile(drive, &cmd);
}
}
printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name,
- q->max_sectors / 2);
+ queue_max_sectors(q) / 2);
if (ata_id_is_ssd(id))
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
memset(&cmd, 0, sizeof(cmd));
cmd.tf.command = on ? ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
- cmd.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+ cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
ret = ide_no_data_taskfile(drive, &cmd);
const struct ide_disk_ops ide_ata_disk_ops = {
.check = ide_disk_check,
+ .set_capacity = ide_disk_set_capacity,
.get_capacity = ide_disk_get_capacity,
.setup = ide_disk_setup,
.flush = ide_disk_flush,