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); |