Commit 1e6c5dfd authored by Jens Axboe's avatar Jens Axboe

[PATCH] Proper 48-bit lba support

parent a04563a1
......@@ -657,7 +657,7 @@ static int icside_dma_read(ide_drive_t *drive)
if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special;
cmd = args->tfRegister[IDE_COMMAND_OFFSET];
} else if (drive->addressing == 1) {
} else if (rq_lba48(rq)) {
cmd = WIN_READDMA_EXT;
} else {
cmd = WIN_READDMA;
......@@ -698,7 +698,7 @@ int icside_dma_write(ide_drive_t *drive)
if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special;
cmd = args->tfRegister[IDE_COMMAND_OFFSET];
} else if (drive->addressing == 1) {
} else if (rq_lba48(rq)) {
cmd = WIN_WRITEDMA_EXT;
} else {
cmd = WIN_WRITEDMA;
......
......@@ -358,7 +358,7 @@ static ide_startstop_t multwrite_intr (ide_drive_t *drive)
static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block)
{
ide_hwif_t *hwif = HWIF(drive);
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
u8 lba48 = rq_lba48(rq);
task_ioreg_t command = WIN_NOP;
ata_nsector_t nsectors;
......@@ -383,7 +383,7 @@ static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, secto
hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
if (drive->select.b.lba) {
if (drive->addressing == 1) {
if (lba48) {
task_ioreg_t tasklets[10];
if (blk_rq_tagged(rq)) {
......@@ -593,7 +593,7 @@ static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, secto
return ide_started;
}
if (drive->addressing == 1) /* 48-bit LBA */
if (rq_lba48(rq)) /* 48-bit LBA */
return lba_48_rw_disk(drive, rq, (unsigned long long) block);
if (drive->select.b.lba) /* 28-bit LBA */
return lba_28_rw_disk(drive, rq, (unsigned long) block);
......@@ -602,9 +602,10 @@ static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, secto
return chs_rw_disk(drive, rq, (unsigned long) block);
}
static task_ioreg_t get_command (ide_drive_t *drive, int cmd)
static task_ioreg_t get_command (ide_drive_t *drive, struct request *rq)
{
int lba48bit = (drive->addressing == 1) ? 1 : 0;
int lba48bit = rq_lba48(rq);
int cmd = rq_data_dir(rq);
if ((cmd == READ) && drive->using_tcq)
return lba48bit ? WIN_READDMA_QUEUED_EXT : WIN_READDMA_QUEUED;
......@@ -631,7 +632,7 @@ static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsi
ide_task_t args;
int sectors;
ata_nsector_t nsectors;
task_ioreg_t command = get_command(drive, rq_data_dir(rq));
task_ioreg_t command = get_command(drive, rq);
unsigned int track = (block / drive->sect);
unsigned int sect = (block % drive->sect) + 1;
unsigned int head = (track % drive->head);
......@@ -663,6 +664,7 @@ static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsi
args.tfRegister[IDE_SELECT_OFFSET] |= drive->select.all;
args.tfRegister[IDE_COMMAND_OFFSET] = command;
args.command_type = ide_cmd_type_parser(&args);
args.addressing = 0;
args.rq = (struct request *) rq;
rq->special = (ide_task_t *)&args;
return do_rw_taskfile(drive, &args);
......@@ -673,7 +675,7 @@ static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, u
ide_task_t args;
int sectors;
ata_nsector_t nsectors;
task_ioreg_t command = get_command(drive, rq_data_dir(rq));
task_ioreg_t command = get_command(drive, rq);
nsectors.all = (u16) rq->nr_sectors;
......@@ -701,6 +703,7 @@ static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, u
args.tfRegister[IDE_SELECT_OFFSET] |= drive->select.all;
args.tfRegister[IDE_COMMAND_OFFSET] = command;
args.command_type = ide_cmd_type_parser(&args);
args.addressing = 0;
args.rq = (struct request *) rq;
rq->special = (ide_task_t *)&args;
return do_rw_taskfile(drive, &args);
......@@ -717,7 +720,7 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, u
ide_task_t args;
int sectors;
ata_nsector_t nsectors;
task_ioreg_t command = get_command(drive, rq_data_dir(rq));
task_ioreg_t command = get_command(drive, rq);
nsectors.all = (u16) rq->nr_sectors;
......@@ -753,6 +756,7 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, u
args.hobRegister[IDE_SELECT_OFFSET_HOB] = drive->select.all;
args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
args.command_type = ide_cmd_type_parser(&args);
args.addressing = 1;
args.rq = (struct request *) rq;
rq->special = (ide_task_t *)&args;
return do_rw_taskfile(drive, &args);
......@@ -1479,7 +1483,7 @@ static int probe_lba_addressing (ide_drive_t *drive, int arg)
static int set_lba_addressing (ide_drive_t *drive, int arg)
{
return (probe_lba_addressing(drive, arg));
return probe_lba_addressing(drive, arg);
}
static void idedisk_add_settings(ide_drive_t *drive)
......@@ -1566,6 +1570,18 @@ static void idedisk_setup (ide_drive_t *drive)
(void) probe_lba_addressing(drive, 1);
if (drive->addressing == 1) {
ide_hwif_t *hwif = HWIF(drive);
int max_s = 2048;
if (max_s > hwif->rqsize)
max_s = hwif->rqsize;
blk_queue_max_sectors(&drive->queue, max_s);
}
printk("%s: max request size: %dKiB\n", drive->name, drive->queue.max_sectors / 2);
/* Extract geometry if we did not already have one for the drive */
if (!drive->cyl || !drive->head || !drive->sect) {
drive->cyl = drive->bios_cyl = id->cyls;
......
......@@ -653,7 +653,7 @@ int __ide_dma_read (ide_drive_t *drive /*, struct request *rq */)
ide_hwif_t *hwif = HWIF(drive);
struct request *rq = HWGROUP(drive)->rq;
unsigned int reading = 1 << 3;
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
u8 lba48 = rq_lba48(rq);
task_ioreg_t command = WIN_NOP;
/* try pio */
......@@ -685,7 +685,7 @@ int __ide_dma_write (ide_drive_t *drive /*, struct request *rq */)
ide_hwif_t *hwif = HWIF(drive);
struct request *rq = HWGROUP(drive)->rq;
unsigned int reading = 0;
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
u8 lba48 = rq_lba48(rq);
task_ioreg_t command = WIN_NOP;
/* try PIO instead of DMA */
......
......@@ -205,7 +205,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG);
args->tfRegister[IDE_STATUS_OFFSET] = stat;
if (drive->addressing == 1) {
if (args->addressing == 1) {
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG);
args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG);
......
......@@ -998,6 +998,7 @@ EXPORT_SYMBOL(save_match);
static void ide_init_queue(ide_drive_t *drive)
{
request_queue_t *q = &drive->queue;
ide_hwif_t *hwif = HWIF(drive);
int max_sectors = 256;
/*
......@@ -1013,8 +1014,15 @@ static void ide_init_queue(ide_drive_t *drive)
drive->queue_setup = 1;
blk_queue_segment_boundary(q, 0xffff);
if (HWIF(drive)->rqsize)
max_sectors = HWIF(drive)->rqsize;
/*
* use rqsize if specified, else set it to defaults for 28-bit or
* 48-bit lba commands
*/
if (hwif->rqsize)
max_sectors = hwif->rqsize;
else
hwif->rqsize = hwif->addressing ? 256 : 65536;
blk_queue_max_sectors(q, max_sectors);
/* IDE DMA can do PRD_ENTRIES number of segments. */
......
......@@ -138,7 +138,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
ide_hwif_t *hwif = HWIF(drive);
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF;
u8 HIHI = (task->addressing == 1) ? 0xE0 : 0xEF;
#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
void debug_taskfile(drive, task);
......@@ -151,7 +151,7 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
}
SELECT_MASK(drive, 0);
if (drive->addressing == 1) {
if (task->addressing == 1) {
hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
......@@ -241,7 +241,7 @@ void ide_end_taskfile (ide_drive_t *drive, u8 stat, u8 err)
args->tfRegister[IDE_STATUS_OFFSET] = stat;
if ((drive->id->command_set_2 & 0x0400) &&
(drive->id->cfs_enable_2 & 0x0400) &&
(drive->addressing == 1)) {
(args->addressing == 1)) {
hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB);
args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG);
args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG);
......@@ -1272,6 +1272,13 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
args.data_phase = req_task->data_phase;
args.command_type = req_task->req_cmd;
/*
* this forces 48-bit commands if the drive is configured to do so.
* it would also be possible to lookup the command type based on the
* opcode, but this is way simpler.
*/
args.addressing = drive->addressing;
#ifdef CONFIG_IDE_TASK_IOCTL_DEBUG
DTF("%s: ide_ioctl_cmd %s: ide_task_cmd %s\n",
drive->name,
......@@ -1611,13 +1618,13 @@ ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
*/
if (task->tf_out_flags.all == 0) {
task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS;
if (drive->addressing == 1)
if (task->addressing == 1)
task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8);
}
if (task->tf_in_flags.all == 0) {
task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
if (drive->addressing == 1)
if (task->addressing == 1)
task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
}
......
......@@ -664,20 +664,20 @@ static ide_startstop_t ide_dma_queued_rw(ide_drive_t *drive, u8 command)
ide_startstop_t __ide_dma_queued_read(ide_drive_t *drive)
{
u8 command = WIN_READDMA_QUEUED;
struct request *rq = hwgroup->rq;
u8 command;
if (drive->addressing == 1)
command = WIN_READDMA_QUEUED_EXT;
command = rq_lba48(rq) ? WIN_READDMA_QUEUED_EXT : WIN_READDMA_QUEUED;
return ide_dma_queued_rw(drive, command);
}
ide_startstop_t __ide_dma_queued_write(ide_drive_t *drive)
{
u8 command = WIN_WRITEDMA_QUEUED;
struct request *rq = hwgroup->rq;
u8 command;
if (drive->addressing == 1)
command = WIN_WRITEDMA_QUEUED_EXT;
command = rq_lba48(rq) ? WIN_WRITEDMA_QUEUED_EXT : WIN_WRITEDMA_QUEUED;
return ide_dma_queued_rw(drive, command);
}
......
......@@ -400,9 +400,20 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
if (err & MARK_ERR) printk("AddrMarkNotFound ");
printk("}");
if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
struct request *rq = HWGROUP(drive)->rq;
int lba48 = drive->addressing;
if (rq) {
if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *t = rq->special;
lba48 = t->addressing;
} else
lba48 = rq_lba48(rq);
}
if ((drive->id->command_set_2 & 0x0400) &&
(drive->id->cfs_enable_2 & 0x0400) &&
(drive->addressing == 1)) {
lba48) {
u64 sectors = 0;
u32 high = 0;
u32 low = ide_read_24(drive);
......
......@@ -535,8 +535,9 @@ static int pdc202xx_quirkproc (ide_drive_t *drive)
static int pdc202xx_old_ide_dma_begin(ide_drive_t *drive)
{
if (drive->addressing == 1) {
struct request *rq = HWGROUP(drive)->rq;
struct request *rq = HWGROUP(drive)->rq;
if (rq_lba48(rq)) {
ide_hwif_t *hwif = HWIF(drive);
// struct pci_dev *dev = hwif->pci_dev;
// unsgned long high_16 = pci_resource_start(dev, 4);
......@@ -557,7 +558,9 @@ static int pdc202xx_old_ide_dma_begin(ide_drive_t *drive)
static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
{
if (drive->addressing == 1) {
struct request *rq = HWGROUP(drive)->rq;
if (rq_lba48(rq)) {
ide_hwif_t *hwif = HWIF(drive);
// unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4);
unsigned long high_16 = hwif->dma_master;
......
......@@ -1240,7 +1240,6 @@ pmac_ide_dma_read (ide_drive_t *drive)
// ide_task_t *args = rq->special;
u8 unit = (drive->select.b.unit & 0x01);
u8 ata4;
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;
if (pmif == NULL)
......@@ -1272,7 +1271,7 @@ pmac_ide_dma_read (ide_drive_t *drive)
command = args->tfRegister[IDE_COMMAND_OFFSET];
}
#else
command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
command = rq_lba48(rq) ? WIN_READDMA_EXT : WIN_READDMA;
if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special;
command = args->tfRegister[IDE_COMMAND_OFFSET];
......@@ -1293,7 +1292,6 @@ pmac_ide_dma_write (ide_drive_t *drive)
// ide_task_t *args = rq->special;
u8 unit = (drive->select.b.unit & 0x01);
u8 ata4;
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;
if (pmif == NULL)
......@@ -1325,7 +1323,7 @@ pmac_ide_dma_write (ide_drive_t *drive)
command = args->tfRegister[IDE_COMMAND_OFFSET];
}
#else
command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
command = rq_lba48(rq) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
if (rq->flags & REQ_DRIVE_TASKFILE) {
ide_task_t *args = rq->special;
command = args->tfRegister[IDE_COMMAND_OFFSET];
......
......@@ -846,6 +846,12 @@ static inline void ide_unmap_buffer(struct request *rq, char *buffer, unsigned l
bio_kunmap_irq(buffer, flags);
}
/*
* must be addressed with 48-bit lba
*/
#define rq_lba48(rq) \
(((rq)->sector + (rq)->nr_sectors) > 0xfffffff || rq->nr_sectors > 256)
#define IDE_CHIPSET_PCI_MASK \
((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
#define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
......@@ -1387,6 +1393,7 @@ typedef struct ide_task_s {
ide_reg_valid_t tf_in_flags;
int data_phase;
int command_type;
int addressing; /* 1 for 48-bit */
ide_pre_handler_t *prehandler;
ide_handler_t *handler;
ide_post_handler_t *posthandler;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment