Index: emcore/trunk/target/ipodclassic/usbtarget.c |
— | — | @@ -69,6 +69,20 @@ |
70 | 70 | size = 16;
|
71 | 71 | break;
|
72 | 72 | }
|
| 73 | + case 0xffff0003: // ATA_BBT_RELOAD
|
| 74 | + {
|
| 75 | + ata_bbt_reload();
|
| 76 | + buffer[0] = 1;
|
| 77 | + size = 16;
|
| 78 | + break;
|
| 79 | + }
|
| 80 | + case 0xffff0004: // ATA_BBT_DISABLE
|
| 81 | + {
|
| 82 | + ata_bbt_disable();
|
| 83 | + buffer[0] = 1;
|
| 84 | + size = 16;
|
| 85 | + break;
|
| 86 | + }
|
73 | 87 | default:
|
74 | 88 | buffer[0] = 2;
|
75 | 89 | size = 16;
|
Index: emcore/trunk/target/ipodclassic/storage_ata-target.h |
— | — | @@ -24,9 +24,18 @@ |
25 | 25 | #ifndef __STORAGE_ATA_TARGET_H__
|
26 | 26 | #define __STORAGE_ATA_TARGET_H__
|
27 | 27 |
|
28 | | -#include "global.h"
|
| 28 | +#include "../global.h"
|
29 | 29 |
|
30 | 30 |
|
| 31 | +struct ata_target_driverinfo
|
| 32 | +{
|
| 33 | + int (*soft_reset)();
|
| 34 | + int (*bbt_translate)(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount);
|
| 35 | + void (*bbt_reload)();
|
| 36 | + void (*bbt_disable)();
|
| 37 | +};
|
| 38 | +
|
| 39 | +
|
31 | 40 | extern uint16_t ata_identify_data[0x100];
|
32 | 41 | extern uint64_t ata_total_sectors;
|
33 | 42 | extern struct mutex ata_mutex;
|
— | — | @@ -35,6 +44,9 @@ |
36 | 45 | extern uint16_t (*ata_bbt)[0x20];
|
37 | 46 | extern uint64_t ata_virtual_sectors;
|
38 | 47 |
|
| 48 | +int ata_bbt_translate(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount);
|
| 49 | +void ata_bbt_reload();
|
| 50 | +void ata_bbt_disable();
|
39 | 51 | int ata_rw_sectors_internal(uint64_t sector, uint32_t count, void* buffer, bool write);
|
40 | 52 | #endif
|
41 | 53 |
|
Index: emcore/trunk/target/ipodclassic/storage_ata.c |
— | — | @@ -26,6 +26,12 @@ |
27 | 27 | #include "timer.h"
|
28 | 28 | #include "../ipodnano3g/s5l8702.h"
|
29 | 29 |
|
| 30 | +
|
| 31 | +#ifndef ATA_RETRIES
|
| 32 | +#define ATA_RETRIES 3
|
| 33 | +#endif
|
| 34 | +
|
| 35 | +
|
30 | 36 | /** static, private data **/
|
31 | 37 | uint16_t ata_identify_data[0x100];
|
32 | 38 | bool ata_lba48;
|
— | — | @@ -56,7 +62,17 @@ |
57 | 63 | }
|
58 | 64 | #endif
|
59 | 65 |
|
| 66 | +static struct ata_target_driverinfo drvinfo =
|
| 67 | +{
|
| 68 | + .soft_reset = ata_soft_reset,
|
| 69 | +#ifdef ATA_HAVE_BBT
|
| 70 | + .bbt_translate = ata_bbt_translate,
|
| 71 | + .bbt_reload = ata_bbt_reload,
|
| 72 | + .bbt_disable = ata_bbt_disable
|
| 73 | +#endif
|
| 74 | +};
|
60 | 75 |
|
| 76 | +
|
61 | 77 | static uint16_t ata_read_cbr(uint32_t volatile* reg)
|
62 | 78 | {
|
63 | 79 | while (!(ATA_PIO_READY & 2)) yield();
|
— | — | @@ -333,6 +349,59 @@ |
334 | 350 | return 0;
|
335 | 351 | }
|
336 | 352 |
|
| 353 | +#ifdef ATA_HAVE_BBT
|
| 354 | +int ata_bbt_translate(uint64_t sector, uint32_t count, uint64_t* phys, uint32_t* physcount)
|
| 355 | +{
|
| 356 | + if (sector + count > ata_virtual_sectors) RET_ERR(0);
|
| 357 | + if (!ata_bbt)
|
| 358 | + {
|
| 359 | + *phys = sector;
|
| 360 | + *physcount = count;
|
| 361 | + return 0;
|
| 362 | + }
|
| 363 | + if (!count)
|
| 364 | + {
|
| 365 | + *phys = 0;
|
| 366 | + *physcount = 0;
|
| 367 | + return 0;
|
| 368 | + }
|
| 369 | + uint32_t offset;
|
| 370 | + uint32_t l0idx = sector >> 15;
|
| 371 | + uint32_t l0offs = sector & 0x7fff;
|
| 372 | + *physcount = MIN(count, 0x8000 - l0offs);
|
| 373 | + uint32_t l0data = ata_bbt[0][l0idx << 1];
|
| 374 | + uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12;
|
| 375 | + if (l0data < 0x8000) offset = l0data + base;
|
| 376 | + else
|
| 377 | + {
|
| 378 | + uint32_t l1idx = (sector >> 10) & 0x1f;
|
| 379 | + uint32_t l1offs = sector & 0x3ff;
|
| 380 | + *physcount = MIN(count, 0x400 - l1offs);
|
| 381 | + uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx];
|
| 382 | + if (l1data < 0x8000) offset = l1data + base;
|
| 383 | + else
|
| 384 | + {
|
| 385 | + uint32_t l2idx = (sector >> 5) & 0x1f;
|
| 386 | + uint32_t l2offs = sector & 0x1f;
|
| 387 | + *physcount = MIN(count, 0x20 - l2offs);
|
| 388 | + uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx];
|
| 389 | + if (l2data < 0x8000) offset = l2data + base;
|
| 390 | + else
|
| 391 | + {
|
| 392 | + uint32_t l3idx = sector & 0x1f;
|
| 393 | + uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx];
|
| 394 | + for (*physcount = 1; *physcount < count && l3idx + *physcount < 0x20; *physcount++)
|
| 395 | + if (ata_bbt[l2data & 0x7fff][l3idx + *physcount] != l3data)
|
| 396 | + break;
|
| 397 | + offset = l3data + base;
|
| 398 | + }
|
| 399 | + }
|
| 400 | + }
|
| 401 | + *phys = sector + offset;
|
| 402 | + return 0;
|
| 403 | +}
|
| 404 | +#endif
|
| 405 | +
|
337 | 406 | int ata_rw_sectors(uint64_t sector, uint32_t count, void* buffer, bool write)
|
338 | 407 | {
|
339 | 408 | #ifdef ATA_HAVE_BBT
|
— | — | @@ -340,39 +409,10 @@ |
341 | 410 | if (ata_bbt)
|
342 | 411 | while (count)
|
343 | 412 | {
|
344 | | - uint32_t offset;
|
345 | | - uint32_t l0idx = sector >> 15;
|
346 | | - uint32_t l0offs = sector & 0x7fff;
|
347 | | - uint32_t cnt = MIN(count, 0x8000 - l0offs);
|
348 | | - uint32_t l0data = ata_bbt[0][l0idx << 1];
|
349 | | - uint32_t base = ata_bbt[0][(l0idx << 1) | 1] << 12;
|
350 | | - if (l0data < 0x8000) offset = l0data + base;
|
351 | | - else
|
352 | | - {
|
353 | | - uint32_t l1idx = (sector >> 10) & 0x1f;
|
354 | | - uint32_t l1offs = sector & 0x3ff;
|
355 | | - cnt = MIN(count, 0x400 - l1offs);
|
356 | | - uint32_t l1data = ata_bbt[l0data & 0x7fff][l1idx];
|
357 | | - if (l1data < 0x8000) offset = l1data + base;
|
358 | | - else
|
359 | | - {
|
360 | | - uint32_t l2idx = (sector >> 5) & 0x1f;
|
361 | | - uint32_t l2offs = sector & 0x1f;
|
362 | | - cnt = MIN(count, 0x20 - l2offs);
|
363 | | - uint32_t l2data = ata_bbt[l1data & 0x7fff][l2idx];
|
364 | | - if (l2data < 0x8000) offset = l2data + base;
|
365 | | - else
|
366 | | - {
|
367 | | - uint32_t l3idx = sector & 0x1f;
|
368 | | - uint32_t l3data = ata_bbt[l2data & 0x7fff][l3idx];
|
369 | | - for (cnt = 1; cnt < count && l3idx + cnt < 0x20; cnt++)
|
370 | | - if (ata_bbt[l2data & 0x7fff][l3idx + cnt] != l3data)
|
371 | | - break;
|
372 | | - offset = l3data + base;
|
373 | | - }
|
374 | | - }
|
375 | | - }
|
376 | | - uint64_t phys = sector + offset;
|
| 413 | + uint64_t phys;
|
| 414 | + uint32_t cnt;
|
| 415 | + PASS_RC(ata_bbt_translate(sector, count, &phys, &cnt), 0, 0);
|
| 416 | + uint32_t offset = phys - sector;
|
377 | 417 | if (offset != ata_last_offset && phys - ata_last_phys < 64) ata_soft_reset();
|
378 | 418 | ata_last_offset = offset;
|
379 | 419 | ata_last_phys = phys + cnt;
|
— | — | @@ -398,20 +438,16 @@ |
399 | 439 | {
|
400 | 440 | uint32_t cnt = MIN(ata_lba48 ? 8192 : 32, count);
|
401 | 441 | int rc = -1;
|
402 | | - int tries = 3;
|
403 | | - while (tries-- && rc)
|
| 442 | + rc = ata_rw_chunk(sector, cnt, buffer, write);
|
| 443 | + if (rc) ata_soft_reset();
|
| 444 | + if (rc && ATA_RETRIES)
|
404 | 445 | {
|
405 | | - rc = ata_rw_chunk(sector, cnt, buffer, write);
|
406 | | - if (rc) ata_soft_reset();
|
407 | | - }
|
408 | | - if (rc)
|
409 | | - {
|
410 | 446 | void* buf = buffer;
|
411 | 447 | uint64_t sect;
|
412 | 448 | for (sect = sector; sect < sector + cnt; sect++)
|
413 | 449 | {
|
414 | 450 | rc = -1;
|
415 | | - tries = 3;
|
| 451 | + tries = ATA_RETRIES;
|
416 | 452 | while (tries-- && rc)
|
417 | 453 | {
|
418 | 454 | rc = ata_rw_chunk(sect, 1, buf, write);
|
— | — | @@ -451,7 +487,13 @@ |
452 | 488 | ata_write_cbr(&ATA_PIO_DAD, BIT(1) | BIT(2));
|
453 | 489 | sleep(10);
|
454 | 490 | ata_write_cbr(&ATA_PIO_DAD, 0);
|
455 | | - PASS_RC_MTX(ata_wait_for_rdy(60000000), 0, 0, &ata_mutex);
|
| 491 | + int rc = ata_wait_for_rdy(20000000);
|
| 492 | + if (IS_ERR(rc))
|
| 493 | + {
|
| 494 | + ata_power_down();
|
| 495 | + sleep(3000000);
|
| 496 | + ata_power_up();
|
| 497 | + }
|
456 | 498 | ata_set_active();
|
457 | 499 | mutex_unlock(&ata_mutex);
|
458 | 500 | }
|
— | — | @@ -512,6 +554,7 @@ |
513 | 555 | (*info).vendor = "Apple";
|
514 | 556 | (*info).product = "iPod Classic";
|
515 | 557 | (*info).revision = "1.0";
|
| 558 | + (*info).driverinfo = &drvinfo;
|
516 | 559 | }
|
517 | 560 |
|
518 | 561 | long ata_last_disk_activity(void)
|
— | — | @@ -519,19 +562,20 @@ |
520 | 563 | return ata_last_activity_value;
|
521 | 564 | }
|
522 | 565 |
|
523 | | -int ata_init(void)
|
| 566 | +#ifdef ATA_HAVE_BBT
|
| 567 | +void ata_bbt_disable()
|
524 | 568 | {
|
525 | | - mutex_init(&ata_mutex);
|
526 | | - wakeup_init(&ata_wakeup);
|
527 | | - PCON(7) = 0x44444444;
|
528 | | - PCON(8) = 0x44444444;
|
529 | | - PCON(9) = 0x44444444;
|
530 | | - PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
|
531 | | - ata_powered = false;
|
532 | | - ata_total_sectors = 0;
|
533 | | -#ifdef ATA_HAVE_BBT
|
534 | 569 | mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
| 570 | + if (ata_bbt) free(ata_bbt);
|
535 | 571 | ata_bbt = NULL;
|
| 572 | + ata_virtual_sectors = ata_total_sectors;
|
| 573 | + mutex_unlock(&ata_mutex);
|
| 574 | +}
|
| 575 | +
|
| 576 | +void ata_bbt_reload()
|
| 577 | +{
|
| 578 | + mutex_lock(&ata_mutex, TIMEOUT_BLOCK);
|
| 579 | + ata_bbt_disable();
|
536 | 580 | ata_power_up();
|
537 | 581 | uint32_t* buf = (uint32_t*)memalign(0x10, 0x1000);
|
538 | 582 | if (buf)
|
— | — | @@ -559,7 +603,22 @@ |
560 | 604 | }
|
561 | 605 | else ata_virtual_sectors = ata_total_sectors;
|
562 | 606 | mutex_unlock(&ata_mutex);
|
| 607 | +}
|
563 | 608 | #endif
|
| 609 | +
|
| 610 | +int ata_init(void)
|
| 611 | +{
|
| 612 | + mutex_init(&ata_mutex);
|
| 613 | + wakeup_init(&ata_wakeup);
|
| 614 | + PCON(7) = 0x44444444;
|
| 615 | + PCON(8) = 0x44444444;
|
| 616 | + PCON(9) = 0x44444444;
|
| 617 | + PCON(10) = (PCON(10) & ~0xffff) | 0x4444;
|
| 618 | + ata_powered = false;
|
| 619 | + ata_total_sectors = 0;
|
| 620 | +#ifdef ATA_HAVE_BBT
|
| 621 | + ata_bbt_reload();
|
| 622 | +#endif
|
564 | 623 | thread_create(&ata_thread_handle, "ATA idle monitor", ata_thread, ata_stack,
|
565 | 624 | sizeof(ata_stack), OS_THREAD, 1, true);
|
566 | 625 | return 0;
|