| Index: emcore/trunk/target/ipodclassic/storage_ata-target.h |
| — | — | @@ -29,7 +29,8 @@ |
| 30 | 30 |
|
| 31 | 31 | struct ata_target_driverinfo
|
| 32 | 32 | {
|
| 33 | | - int (*soft_reset)();
|
| | 33 | + void (*srst_after_error)(bool enable);
|
| | 34 | + void (*set_retries)(int retries);
|
| 34 | 35 | int (*bbt_translate)(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount);
|
| 35 | 36 | void (*bbt_reload)();
|
| 36 | 37 | void (*bbt_disable)();
|
| — | — | @@ -40,6 +41,9 @@ |
| 41 | 42 | extern uint64_t ata_total_sectors;
|
| 42 | 43 | extern struct mutex ata_mutex;
|
| 43 | 44 |
|
| | 45 | +void ata_set_retries(int retries);
|
| | 46 | +void ata_srst_after_error(bool enable);
|
| | 47 | +
|
| 44 | 48 | #ifdef ATA_HAVE_BBT
|
| 45 | 49 | extern uint16_t (*ata_bbt)[0x20];
|
| 46 | 50 | extern uint64_t ata_virtual_sectors;
|
| Index: emcore/trunk/target/ipodclassic/storage_ata.c |
| — | — | @@ -45,6 +45,8 @@ |
| 46 | 46 | static struct scheduler_thread ata_thread_handle;
|
| 47 | 47 | static uint32_t ata_stack[0x80] STACK_ATTR;
|
| 48 | 48 | static bool ata_powered;
|
| | 49 | +static int ata_retries = ATA_RETRIES;
|
| | 50 | +static bool ata_error_srst = true;
|
| 49 | 51 |
|
| 50 | 52 | #ifdef ATA_HAVE_BBT
|
| 51 | 53 | #include "panic.h"
|
| — | — | @@ -53,18 +55,24 @@ |
| 54 | 56 | uint32_t ata_last_offset;
|
| 55 | 57 | uint64_t ata_last_phys;
|
| 56 | 58 |
|
| 57 | | -void ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer)
|
| | 59 | +int ata_bbt_read_sectors(uint32_t sector, uint32_t count, void* buffer)
|
| 58 | 60 | {
|
| | 61 | + if (ata_last_phys != sector - 1 && ata_last_phys > sector - 64) ata_soft_reset();
|
| 59 | 62 | int rc = ata_rw_sectors_internal(sector, count, buffer, false);
|
| | 63 | + if (rc) rc = ata_rw_sectors_internal(sector, count, buffer, false);
|
| | 64 | + ata_last_phys = sector + count - 1;
|
| | 65 | + ata_last_offset = 0;
|
| 60 | 66 | if (IS_ERR(rc))
|
| 61 | | - panicf(PANIC_KILLTHREAD, "ATA: Error %08X while reading BBT (sector %d, count %d)\n",
|
| 62 | | - rc, sector, count);
|
| | 67 | + cprintf(CONSOLE_BOOT, "ATA: Error %08X while reading BBT (sector %d, count %d)\n",
|
| | 68 | + rc, sector, count);
|
| | 69 | + return rc;
|
| 63 | 70 | }
|
| 64 | 71 | #endif
|
| 65 | 72 |
|
| 66 | 73 | static struct ata_target_driverinfo drvinfo =
|
| 67 | 74 | {
|
| 68 | | - .soft_reset = ata_soft_reset,
|
| | 75 | + .set_retries = ata_set_retries,
|
| | 76 | + .srst_after_error = ata_srst_after_error,
|
| 69 | 77 | #ifdef ATA_HAVE_BBT
|
| 70 | 78 | .bbt_translate = ata_bbt_translate,
|
| 71 | 79 | .bbt_reload = ata_bbt_reload,
|
| — | — | @@ -73,6 +81,16 @@ |
| 74 | 82 | };
|
| 75 | 83 |
|
| 76 | 84 |
|
| | 85 | +void ata_set_retries(int retries)
|
| | 86 | +{
|
| | 87 | + ata_retries = retries;
|
| | 88 | +}
|
| | 89 | +
|
| | 90 | +void ata_srst_after_error(bool enable)
|
| | 91 | +{
|
| | 92 | + ata_error_srst = enable;
|
| | 93 | +}
|
| | 94 | +
|
| 77 | 95 | static uint16_t ata_read_cbr(uint32_t volatile* reg)
|
| 78 | 96 | {
|
| 79 | 97 | while (!(ATA_PIO_READY & 2)) yield();
|
| — | — | @@ -151,6 +169,16 @@ |
| 152 | 170 | ata_last_activity_value = USEC_TIMER;
|
| 153 | 171 | }
|
| 154 | 172 |
|
| | 173 | +bool ata_disk_is_active(void)
|
| | 174 | +{
|
| | 175 | + return ata_powered;
|
| | 176 | +}
|
| | 177 | +
|
| | 178 | +int ata_num_drives(void)
|
| | 179 | +{
|
| | 180 | + return 1;
|
| | 181 | +}
|
| | 182 | +
|
| 155 | 183 | int ata_set_feature(uint32_t feature, uint32_t param)
|
| 156 | 184 | {
|
| 157 | 185 | PASS_RC(ata_wait_for_rdy(500000), 1, 0);
|
| — | — | @@ -439,8 +467,8 @@ |
| 440 | 468 | uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count);
|
| 441 | 469 | int rc = -1;
|
| 442 | 470 | rc = ata_rw_chunk(sector, cnt, buffer, write);
|
| 443 | | - if (rc) ata_soft_reset();
|
| 444 | | - if (rc && ATA_RETRIES)
|
| | 471 | + if (rc && ata_error_srst) ata_soft_reset();
|
| | 472 | + if (rc && ata_retries)
|
| 445 | 473 | {
|
| 446 | 474 | void* buf = buffer;
|
| 447 | 475 | uint64_t sect;
|
| — | — | @@ -447,11 +475,11 @@ |
| 448 | 476 | for (sect = sector; sect < sector + cnt; sect++)
|
| 449 | 477 | {
|
| 450 | 478 | rc = -1;
|
| 451 | | - int tries = ATA_RETRIES;
|
| | 479 | + int tries = ata_retries;
|
| 452 | 480 | while (tries-- && rc)
|
| 453 | 481 | {
|
| 454 | 482 | rc = ata_rw_chunk(sect, 1, buf, write);
|
| 455 | | - if (rc) ata_soft_reset();
|
| | 483 | + if (rc && ata_error_srst) ata_soft_reset();
|
| 456 | 484 | }
|
| 457 | 485 | if (rc) break;
|
| 458 | 486 | buf += SECTOR_SIZE;
|
| — | — | @@ -496,6 +524,7 @@ |
| 497 | 525 | }
|
| 498 | 526 | ata_set_active();
|
| 499 | 527 | mutex_unlock(&ata_mutex);
|
| | 528 | + return rc;
|
| 500 | 529 | }
|
| 501 | 530 |
|
| 502 | 531 | int ata_read_sectors(IF_MD2(int drive,) unsigned long start, int incount,
|
| — | — | @@ -580,23 +609,38 @@ |
| 581 | 610 | uint32_t* buf = (uint32_t*)memalign(0x10, 0x1000);
|
| 582 | 611 | if (buf)
|
| 583 | 612 | {
|
| 584 | | - ata_bbt_read_sectors(0, 1, buf);
|
| 585 | | - if (!memcmp(buf, "emBIbbth", 8))
|
| | 613 | + if (IS_ERR(ata_bbt_read_sectors(0, 1, buf)))
|
| | 614 | + ata_virtual_sectors = ata_total_sectors;
|
| | 615 | + else if (!memcmp(buf, "emBIbbth", 8))
|
| 586 | 616 | {
|
| 587 | 617 | ata_virtual_sectors = (((uint64_t)buf[0x1fd]) << 32) | buf[0x1fc];
|
| 588 | 618 | uint32_t count = buf[0x1ff];
|
| 589 | 619 | ata_bbt = (typeof(ata_bbt))memalign(0x10, 0x1000 * count);
|
| 590 | | - uint32_t i;
|
| 591 | | - uint32_t cnt;
|
| 592 | | - for (i = 0; i < count; i += cnt)
|
| | 620 | + if (!ata_bbt)
|
| 593 | 621 | {
|
| 594 | | - uint32_t phys = buf[0x200 + i];
|
| 595 | | - for (cnt = 1; cnt < count; cnt++)
|
| 596 | | - if (buf[0x200 + i + cnt] != phys + cnt)
|
| | 622 | + cprintf(CONSOLE_BOOT, "ATA: Failed to allocate memory for BBT! (%d bytes)",
|
| | 623 | + 0x1000 * count);
|
| | 624 | + ata_virtual_sectors = ata_total_sectors;
|
| | 625 | + }
|
| | 626 | + else
|
| | 627 | + {
|
| | 628 | + uint32_t i;
|
| | 629 | + uint32_t cnt;
|
| | 630 | + for (i = 0; i < count; i += cnt)
|
| | 631 | + {
|
| | 632 | + uint32_t phys = buf[0x200 + i];
|
| | 633 | + for (cnt = 1; cnt < count; cnt++)
|
| | 634 | + if (buf[0x200 + i + cnt] != phys + cnt)
|
| | 635 | + break;
|
| | 636 | + if (IS_ERR(ata_bbt_read_sectors(phys, cnt, ata_bbt[i << 6])))
|
| | 637 | + {
|
| | 638 | + free(ata_bbt);
|
| | 639 | + ata_virtual_sectors = ata_total_sectors;
|
| 597 | 640 | break;
|
| 598 | | - ata_bbt_read_sectors(phys, cnt, ata_bbt[i << 6]);
|
| | 641 | + }
|
| | 642 | + }
|
| | 643 | + if (ata_bbt) reownalloc(ata_bbt, NULL);
|
| 599 | 644 | }
|
| 600 | | - reownalloc(ata_bbt, NULL);
|
| 601 | 645 | }
|
| 602 | 646 | else ata_virtual_sectors = ata_total_sectors;
|
| 603 | 647 | free(buf);
|