aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ide/ide-io.c68
-rw-r--r--drivers/ide/ide-iops.c8
-rw-r--r--drivers/ide/ide-lib.c69
-rw-r--r--include/linux/ide.h24
4 files changed, 106 insertions, 63 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 48c38b68bd36..e053e00a7058 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -297,6 +297,48 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
297 spin_unlock_irqrestore(&ide_lock, flags); 297 spin_unlock_irqrestore(&ide_lock, flags);
298} 298}
299 299
300void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
301{
302 ide_hwif_t *hwif = drive->hwif;
303 struct ide_taskfile *tf = &task->tf;
304
305 if (task->tf_flags & IDE_TFLAG_IN_DATA) {
306 u16 data = hwif->INW(IDE_DATA_REG);
307
308 tf->data = data & 0xff;
309 tf->hob_data = (data >> 8) & 0xff;
310 }
311
312 /* be sure we're looking at the low order bits */
313 hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
314
315 if (task->tf_flags & IDE_TFLAG_IN_NSECT)
316 tf->nsect = hwif->INB(IDE_NSECTOR_REG);
317 if (task->tf_flags & IDE_TFLAG_IN_LBAL)
318 tf->lbal = hwif->INB(IDE_SECTOR_REG);
319 if (task->tf_flags & IDE_TFLAG_IN_LBAM)
320 tf->lbam = hwif->INB(IDE_LCYL_REG);
321 if (task->tf_flags & IDE_TFLAG_IN_LBAH)
322 tf->lbah = hwif->INB(IDE_HCYL_REG);
323 if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
324 tf->device = hwif->INB(IDE_SELECT_REG);
325
326 if (task->tf_flags & IDE_TFLAG_LBA48) {
327 hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
328
329 if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
330 tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
331 if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
332 tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG);
333 if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
334 tf->hob_lbal = hwif->INB(IDE_SECTOR_REG);
335 if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
336 tf->hob_lbam = hwif->INB(IDE_LCYL_REG);
337 if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
338 tf->hob_lbah = hwif->INB(IDE_HCYL_REG);
339 }
340}
341
300/** 342/**
301 * ide_end_drive_cmd - end an explicit drive command 343 * ide_end_drive_cmd - end an explicit drive command
302 * @drive: command 344 * @drive: command
@@ -339,30 +381,14 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
339 if (args) { 381 if (args) {
340 struct ide_taskfile *tf = &args->tf; 382 struct ide_taskfile *tf = &args->tf;
341 383
342 if (args->tf_flags & IDE_TFLAG_IN_DATA) {
343 u16 data = hwif->INW(IDE_DATA_REG);
344
345 tf->data = data & 0xff;
346 tf->hob_data = (data >> 8) & 0xff;
347 }
348 tf->error = err; 384 tf->error = err;
349 /* be sure we're looking at the low order bits */
350 hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
351 tf->nsect = hwif->INB(IDE_NSECTOR_REG);
352 tf->lbal = hwif->INB(IDE_SECTOR_REG);
353 tf->lbam = hwif->INB(IDE_LCYL_REG);
354 tf->lbah = hwif->INB(IDE_HCYL_REG);
355 tf->device = hwif->INB(IDE_SELECT_REG);
356 tf->status = stat; 385 tf->status = stat;
357 386
358 if (args->tf_flags & IDE_TFLAG_LBA48) { 387 args->tf_flags |= (IDE_TFLAG_IN_TF|IDE_TFLAG_IN_DEVICE);
359 hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG); 388 if (args->tf_flags & IDE_TFLAG_LBA48)
360 tf->hob_feature = hwif->INB(IDE_FEATURE_REG); 389 args->tf_flags |= IDE_TFLAG_IN_HOB;
361 tf->hob_nsect = hwif->INB(IDE_NSECTOR_REG); 390
362 tf->hob_lbal = hwif->INB(IDE_SECTOR_REG); 391 ide_tf_read(drive, args);
363 tf->hob_lbam = hwif->INB(IDE_LCYL_REG);
364 tf->hob_lbah = hwif->INB(IDE_HCYL_REG);
365 }
366 } 392 }
367 } else if (blk_pm_request(rq)) { 393 } else if (blk_pm_request(rq)) {
368 struct request_pm_state *pm = rq->data; 394 struct request_pm_state *pm = rq->data;
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 38d6b15d6c47..c97c0719ddf1 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -158,14 +158,6 @@ void default_hwif_mmiops (ide_hwif_t *hwif)
158 158
159EXPORT_SYMBOL(default_hwif_mmiops); 159EXPORT_SYMBOL(default_hwif_mmiops);
160 160
161u32 ide_read_24 (ide_drive_t *drive)
162{
163 u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG);
164 u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG);
165 u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG);
166 return (hcyl<<16)|(lcyl<<8)|sect;
167}
168
169void SELECT_DRIVE (ide_drive_t *drive) 161void SELECT_DRIVE (ide_drive_t *drive)
170{ 162{
171 if (HWIF(drive)->selectproc) 163 if (HWIF(drive)->selectproc)
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 001085845a79..15736d4ce9b4 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -479,6 +479,42 @@ static void ide_dump_opcode(ide_drive_t *drive)
479 printk("0x%02x\n", opcode); 479 printk("0x%02x\n", opcode);
480} 480}
481 481
482static u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
483{
484 u32 high, low;
485
486 if (lba48)
487 high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) |
488 tf->hob_lbal;
489 else
490 high = tf->device & 0xf;
491 low = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
492
493 return ((u64)high << 24) | low;
494}
495
496static void ide_dump_sector(ide_drive_t *drive)
497{
498 ide_task_t task;
499 struct ide_taskfile *tf = &task.tf;
500 int lba48 = (drive->addressing == 1) ? 1 : 0;
501
502 memset(&task, 0, sizeof(task));
503 if (lba48)
504 task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
505 IDE_TFLAG_LBA48;
506 else
507 task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
508
509 ide_tf_read(drive, &task);
510
511 if (lba48 || (tf->device & ATA_LBA))
512 printk(", LBAsect=%llu", ide_get_lba_addr(tf, lba48));
513 else
514 printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
515 tf->device & 0xf, tf->lbal);
516}
517
482static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) 518static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
483{ 519{
484 ide_hwif_t *hwif = HWIF(drive); 520 ide_hwif_t *hwif = HWIF(drive);
@@ -512,38 +548,7 @@ static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
512 printk("}"); 548 printk("}");
513 if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR || 549 if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
514 (err & (ECC_ERR|ID_ERR|MARK_ERR))) { 550 (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
515 if (drive->addressing == 1) { 551 ide_dump_sector(drive);
516 __u64 sectors = 0;
517 u32 low = 0, high = 0;
518 hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
519 low = ide_read_24(drive);
520 hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
521 high = ide_read_24(drive);
522 sectors = ((__u64)high << 24) | low;
523 printk(", LBAsect=%llu, high=%d, low=%d",
524 (unsigned long long) sectors,
525 high, low);
526 } else {
527 u8 sector, lcyl, hcyl, cur;
528
529 sector = hwif->INB(IDE_SECTOR_REG);
530 lcyl = hwif->INB(IDE_LCYL_REG);
531 hcyl = hwif->INB(IDE_HCYL_REG);
532 cur = hwif->INB(IDE_SELECT_REG);
533
534 if (cur & 0x40) { /* using LBA? */
535 printk(", LBAsect=%ld", (unsigned long)
536 ((cur & 0xf) << 24) |
537 (hcyl << 16) |
538 (lcyl << 8) |
539 sector);
540 } else {
541 printk(", CHS=%d/%d/%d",
542 (hcyl << 8) + lcyl,
543 cur & 0xf,
544 sector);
545 }
546 }
547 if (HWGROUP(drive) && HWGROUP(drive)->rq) 552 if (HWGROUP(drive) && HWGROUP(drive)->rq)
548 printk(", sector=%llu", 553 printk(", sector=%llu",
549 (unsigned long long)HWGROUP(drive)->rq->sector); 554 (unsigned long long)HWGROUP(drive)->rq->sector);
diff --git a/include/linux/ide.h b/include/linux/ide.h
index c333a7528d94..67f98c096c03 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -913,6 +913,27 @@ enum {
913 IDE_TFLAG_IN_DATA = (1 << 17), 913 IDE_TFLAG_IN_DATA = (1 << 17),
914 IDE_TFLAG_CUSTOM_HANDLER = (1 << 18), 914 IDE_TFLAG_CUSTOM_HANDLER = (1 << 18),
915 IDE_TFLAG_DMA_PIO_FALLBACK = (1 << 19), 915 IDE_TFLAG_DMA_PIO_FALLBACK = (1 << 19),
916 IDE_TFLAG_IN_HOB_FEATURE = (1 << 20),
917 IDE_TFLAG_IN_HOB_NSECT = (1 << 21),
918 IDE_TFLAG_IN_HOB_LBAL = (1 << 22),
919 IDE_TFLAG_IN_HOB_LBAM = (1 << 23),
920 IDE_TFLAG_IN_HOB_LBAH = (1 << 24),
921 IDE_TFLAG_IN_HOB_LBA = IDE_TFLAG_IN_HOB_LBAL |
922 IDE_TFLAG_IN_HOB_LBAM |
923 IDE_TFLAG_IN_HOB_LBAH,
924 IDE_TFLAG_IN_HOB = IDE_TFLAG_IN_HOB_FEATURE |
925 IDE_TFLAG_IN_HOB_NSECT |
926 IDE_TFLAG_IN_HOB_LBA,
927 IDE_TFLAG_IN_NSECT = (1 << 25),
928 IDE_TFLAG_IN_LBAL = (1 << 26),
929 IDE_TFLAG_IN_LBAM = (1 << 27),
930 IDE_TFLAG_IN_LBAH = (1 << 28),
931 IDE_TFLAG_IN_LBA = IDE_TFLAG_IN_LBAL |
932 IDE_TFLAG_IN_LBAM |
933 IDE_TFLAG_IN_LBAH,
934 IDE_TFLAG_IN_TF = IDE_TFLAG_IN_NSECT |
935 IDE_TFLAG_IN_LBA,
936 IDE_TFLAG_IN_DEVICE = (1 << 29),
916}; 937};
917 938
918struct ide_taskfile { 939struct ide_taskfile {
@@ -956,8 +977,7 @@ typedef struct ide_task_s {
956} ide_task_t; 977} ide_task_t;
957 978
958void ide_tf_load(ide_drive_t *, ide_task_t *); 979void ide_tf_load(ide_drive_t *, ide_task_t *);
959 980void ide_tf_read(ide_drive_t *, ide_task_t *);
960extern u32 ide_read_24(ide_drive_t *);
961 981
962extern void SELECT_DRIVE(ide_drive_t *); 982extern void SELECT_DRIVE(ide_drive_t *);
963extern void SELECT_MASK(ide_drive_t *, int); 983extern void SELECT_MASK(ide_drive_t *, int);