diff options
| author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-01-25 16:17:17 -0500 |
|---|---|---|
| committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-01-25 16:17:17 -0500 |
| commit | c2b57cdc1d2976444d451a2a2e43e11b61ed0638 (patch) | |
| tree | f322e4d494d9688afd319fbe88afd6a526bb0154 | |
| parent | d32444771b154c3ec37ebf6439004653560c2411 (diff) | |
ide: add ide_tf_read() helper
* Factor out code reading taskfile registers from ide_end_drive_cmd()
to the new ide_tf_read() helper.
* Add IDE_TFLAG_IN_* taskfile flags to indicate the need to load
particular IDE taskfile register in ide_tf_read().
* Update ide_end_drive_cmd() to set respective IDE_TFLAG_IN_* taksfile flags.
* Add ide_get_lba_addr() for getting LBA sector address from taskfile struct.
* Factor out code getting sector address from ide_dump_ata_status()
to the new ide_dump_sector() function.
* Convert ide_dump_sector() to use ide_tf_read() and ide_get_lba_addr().
* Remove no longer needed ide_read_24().
The only change in functionality caused by this patch is that
ide_dump_ata_status() no longer prints "high"/"low" parts of LBA48
sector address (of course LBA48 sector address is still printed).
Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
| -rw-r--r-- | drivers/ide/ide-io.c | 68 | ||||
| -rw-r--r-- | drivers/ide/ide-iops.c | 8 | ||||
| -rw-r--r-- | drivers/ide/ide-lib.c | 69 | ||||
| -rw-r--r-- | include/linux/ide.h | 24 |
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 | ||
| 300 | void 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 | ||
| 159 | EXPORT_SYMBOL(default_hwif_mmiops); | 159 | EXPORT_SYMBOL(default_hwif_mmiops); |
| 160 | 160 | ||
| 161 | u32 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 | |||
| 169 | void SELECT_DRIVE (ide_drive_t *drive) | 161 | void 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 | ||
| 482 | static 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 | |||
| 496 | static 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 | |||
| 482 | static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat) | 518 | static 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 | ||
| 918 | struct ide_taskfile { | 939 | struct ide_taskfile { |
| @@ -956,8 +977,7 @@ typedef struct ide_task_s { | |||
| 956 | } ide_task_t; | 977 | } ide_task_t; |
| 957 | 978 | ||
| 958 | void ide_tf_load(ide_drive_t *, ide_task_t *); | 979 | void ide_tf_load(ide_drive_t *, ide_task_t *); |
| 959 | 980 | void ide_tf_read(ide_drive_t *, ide_task_t *); | |
| 960 | extern u32 ide_read_24(ide_drive_t *); | ||
| 961 | 981 | ||
| 962 | extern void SELECT_DRIVE(ide_drive_t *); | 982 | extern void SELECT_DRIVE(ide_drive_t *); |
| 963 | extern void SELECT_MASK(ide_drive_t *, int); | 983 | extern void SELECT_MASK(ide_drive_t *, int); |
