diff options
Diffstat (limited to 'drivers/ide/ide-disk.c')
-rw-r--r-- | drivers/ide/ide-disk.c | 85 |
1 files changed, 42 insertions, 43 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 9b63e15d67e..20d357e9329 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -140,6 +140,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, u8 lba48 = (drive->addressing == 1) ? 1 : 0; u8 command = WIN_NOP; ata_nsector_t nsectors; + struct ide_taskfile ltf, *tf = <f; nsectors.all = (u16) rq->nr_sectors; @@ -160,53 +161,36 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, /* FIXME: SELECT_MASK(drive, 0) ? */ + memset(tf, 0, sizeof(*tf)); + if (drive->select.b.lba) { if (lba48) { - u8 tasklets[10]; - pr_debug("%s: LBA=0x%012llx\n", drive->name, (unsigned long long)block); - tasklets[0] = 0; - tasklets[1] = 0; - tasklets[2] = nsectors.b.low; - tasklets[3] = nsectors.b.high; - tasklets[4] = (u8) block; - tasklets[5] = (u8)(block >> 8); - tasklets[6] = (u8)(block >> 16); - tasklets[7] = (u8)(block >> 24); - if (sizeof(block) == 4) { - tasklets[8] = 0; - tasklets[9] = 0; - } else { - tasklets[8] = (u8)((u64)block >> 32); - tasklets[9] = (u8)((u64)block >> 40); + tf->hob_nsect = nsectors.b.high; + 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.b.low; + tf->lbal = (u8) block; + tf->lbam = (u8)(block >> 8); + tf->lbah = (u8)(block >> 16); #ifdef DEBUG printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", - drive->name, tasklets[3], tasklets[2], - tasklets[9], tasklets[8], tasklets[7], - tasklets[6], tasklets[5], tasklets[4]); + drive->name, tf->hob_nsect, tf->nsect, + tf->hob_lbah, tf->hob_lbam, tf->hob_lbal, + tf->lbah, tf->lbam, tf->lbal); #endif - hwif->OUTB(tasklets[1], IDE_FEATURE_REG); - hwif->OUTB(tasklets[3], IDE_NSECTOR_REG); - hwif->OUTB(tasklets[7], IDE_SECTOR_REG); - hwif->OUTB(tasklets[8], IDE_LCYL_REG); - hwif->OUTB(tasklets[9], IDE_HCYL_REG); - - hwif->OUTB(tasklets[0], IDE_FEATURE_REG); - hwif->OUTB(tasklets[2], IDE_NSECTOR_REG); - hwif->OUTB(tasklets[4], IDE_SECTOR_REG); - hwif->OUTB(tasklets[5], IDE_LCYL_REG); - hwif->OUTB(tasklets[6], IDE_HCYL_REG); - hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG); } else { - hwif->OUTB(0x00, IDE_FEATURE_REG); - hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); - hwif->OUTB(block, IDE_SECTOR_REG); - hwif->OUTB(block>>=8, IDE_LCYL_REG); - hwif->OUTB(block>>=8, IDE_HCYL_REG); - hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG); + tf->nsect = nsectors.b.low; + tf->lbal = block; + tf->lbam = block >>= 8; + tf->lbah = block >>= 8; + tf->device = (block >> 8) & 0xf; } } else { unsigned int sect,head,cyl,track; @@ -217,14 +201,29 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); - hwif->OUTB(0x00, IDE_FEATURE_REG); - hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); - hwif->OUTB(sect, IDE_SECTOR_REG); - hwif->OUTB(cyl, IDE_LCYL_REG); - hwif->OUTB(cyl>>8, IDE_HCYL_REG); - hwif->OUTB(head|drive->select.all,IDE_SELECT_REG); + tf->nsect = nsectors.b.low; + tf->lbal = sect; + tf->lbam = cyl; + tf->lbah = cyl >> 8; + tf->device = head; } + if (drive->select.b.lba && lba48) { + hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG); + hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG); + hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG); + hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG); + hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG); + } + + hwif->OUTB(tf->feature, IDE_FEATURE_REG); + hwif->OUTB(tf->nsect, IDE_NSECTOR_REG); + hwif->OUTB(tf->lbal, IDE_SECTOR_REG); + hwif->OUTB(tf->lbam, IDE_LCYL_REG); + hwif->OUTB(tf->lbah, IDE_HCYL_REG); + + hwif->OUTB(tf->device | drive->select.all, IDE_SELECT_REG); + if (dma) { if (!hwif->dma_setup(drive)) { if (rq_data_dir(rq)) { |